OO Design Patterns Why Design Patterns?: Design Patterns, Elements of Reusable Object-Oriented Software
OO Design Patterns Why Design Patterns?: Design Patterns, Elements of Reusable Object-Oriented Software
Ref: Design Patterns, Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson, & Vlissides
[aka The Gang of Four]
Addison-Welsley, 1995. Basic idea: Reusable metaphors for designing OO software systems.
[But not all patterns are truly OO.]
When confronted with endless possibilities, rely on those who have gone before you:
CS211 ooDesignPatterns
When this book came out, it caused a lot of excitement: Resonance with professional software developers. Oh yeah, Ive seen that before. We call it XXX in our group. Put into writing a lot of shared knowledge. Some people complained: Whats the big deal? Everyone knows that! Book describes 23 patterns: name and description abstract representation examples (high-level and code-level) applicability and usefulness
We software professionals have done a poor job of writing down what weve learned.
CS211 ooDesignPatterns
There are thousands of patterns out there and thousands more waiting to be discovered: Some are domain specic. Some are a lot like others, special cases, etc. There is no ocial person or group who decides what is/isnt a design pattern: many DP web pages newsgroups discussions more books academic conferences special term: patterns geek
CS211 ooDesignPatterns
CS211 ooDesignPatterns
communicate about systems with other developers give guidance in resolving non-functional requirements and trade-os: portability extensibility maintainability, re-usability, scalability avoid known traps, pitfalls, and temptations ease restructuring, refactoring coherent, directed system evolution and maintenance
Think of as a low-level software architecture or a high-level programming abstraction. First, you learn the basics (data structures, algorithms, tool and lang details). Then, you learn modules/interfaces/information hiding, classes/OO programming. Design patterns are at the next level of abstraction: read, read, read, think, think, think, apply!
[How do chess players become world class?]
Design patterns help you: design new systems using higher-level abstractions than variables, procedures, and classes. understand relative tradeos, appropriateness, (dis)advantages of patterns understand essence of what youre constructing
CS211 ooDesignPatterns
CS211 ooDesignPatterns
Graphical Notation
[similar to Rumbaughs OMT]
className methodSig(); a class (with methods and vars)
methodSig();
methodImpl()
CS211 ooDesignPatterns
object
an object
When we want to reuse classes in an application that expects classes with a dierent and incompatible interface, we do not want to (and often cannot) change the reusable classes to suit our application.
CS211 ooDesignPatterns
Example of the Adapter Pattern
Editor Shape BoundingBox() CreateManipulator() TextView
GetExtent() text
TextShape
BoundingBox() CreateManipulator() return text -> GetExtent() return new TextManipulator
Client
Target Request()
Adaptee
SpecificRequest()
(implementation)
Adapter
Request() SpecificRequest()
LineShape
BoundingBox() CreateManipulator()
Client
Target Request()
Adaptee
SpecificRequest()
CS211 ooDesignPatterns
adaptee
Adapter
Request() adaptee -> SpecificRequest()
CS211 ooDesignPatterns
10
CS211 ooDesignPatterns
11
CS211 ooDesignPatterns
12
Intent:
Xwindow
But sometimes, we want a hierarchy for A on its own, independent of these concrete classes:
Window
Decouple an abstraction from its implementation so the two can vary independently. Motivation: Usually, when an abstraction has several possible implementations, use an abstract base class with several concrete derived classes:
AbsClass
MSwindow
IconWindow
TransientWindow
IconXwindow
IconMSwindow
TransientXwindow
and add switch statement to all routines, ... but this defeats OO programming and polymorphism!
CS211 ooDesignPatterns
13
The basic problem is that we have two dimensions: 1. Abstract windows i.e., Window, IconWindow, TransientWindow 2. Window implementations i.e., X, MS, MacOS Bridge solution: use two inheritance hierarchies and add a level of indirection.
Bridge
Window
DrawText() DrawRect() impl
Bridge
less maintainable
CS211 ooDesignPatterns
14
Abstraction
Operation()
impl
Implementor
OperationImpl()
WindowImpl
DevDrawText() DevDrawLIne()
RefinedAbstraction
ConcreteImplementorA
OperationImpl()
ConcreteImplementorB
OperationImpl()
CS211 ooDesignPatterns
TransientWindow
IconWindow
DrawCloseBox()
XWindowImp
DevDrawText() DevDrawLine()
MSWindowImp
DevDrawText() DevDrawLine()
DrawBorder()
DrawRect() DrawText()
DrawRect()
XDrawLine()
XDrawString()
15
CS211 ooDesignPatterns
16
Participants
Abstraction (Window) denes interface of abstraction maintains a reference to an object of Implementor RenedAbstraction (Icon Window) extends interface of Abstraction Implementor (WindowImpl) denes interface for implementation classes often quite dierent from Abstraction usually denes primitives which Abstraction combines usefully
CS211 ooDesignPatterns
Line
Draw()
17
CS211 ooDesignPatterns
18
Graphic Draw()
graphics
children
Rect.
Draw()
Text
Draw()
GraphicContainer
Draw() Add(Graphic) Remove(Graphic) GetChild(int) forall g in graphics g.Draw()
Leaf
Operation()
Leaf
Operation()
ComponentContainer
Operation() Add(Component) Remove(Component) GetChild(int) forall g in children g.Operation()
CS211 ooDesignPatterns
Picture
Draw() Add(Graphic) Remove(Graphic) GetChild(int)
19
ConcreteCompContainer1
Operation() Add(Component) Remove(Component) GetChild(int)
ConcreteCompContainer2
Operation() Add(Component) Remove(Component) GetChild(int)
CS211 ooDesignPatterns
20
Notes on the Composite Pattern
Gamma et al. think that the management routines should be declared at the top level, even if leaves (e.g., Rectangle) have no use for them their motivation is transparency: only one interface which everyone implements. This is WRONG OO-wise. If you use a second interface (i.e., Container), can still use the Graphic interface most of the time
CS211 ooDesignPatterns
Client
Why did they do this? Confusion of C++ RTTI with proper dynamic type information. This is completely safe in Java.
21
CS211 ooDesignPatterns
22
ComponentContainer (GraphicContainer ) Denes interface for components having children. Stores child components. Implements some child-related operations in the component interface; defers others to its derived classes ConcreteCompContainer (Picture) Denes remaining behavior (for components having children) not dened by ComponentContainer.
Intent: Provide a single, unied interface to a set of interface/modules in a subsystem. Abstracts a whole subsystem into one interface. Motivation: Reduce complexity of a system. Increase cohesion within a subsystem and reduce coupling with other parts of the system.
CS211 ooDesignPatterns
23
Fewer, simpler, interactions within system Easier to use, reuse Easier to replace components.
CS211 ooDesignPatterns
24
Client Classes
Facade
ProgNodeBuilder RISCCG ProgNode StackMachineCG
StatementNode
CS211 ooDesignPatterns
ExpressionNode VariableNode
25
Subsystem Classes
CS211 ooDesignPatterns
26
MINITUNIS
USER_SYS
main Control Family User State
Knows which subsystem classes are responsible for a request. Delegates client requests to appropriate subsystem objects. Subsystem still does the work; facade just directs trac. Subsystem Classes (Other SS components)
FILE_SYS
File Directory FileTable Computer Memory
INODE_SYS
Inode InodeTable FileIO FreeInode InodeGlobals Disk DiskMutex
DEVICE_SYS
DeviceDriver Tty
CS211 ooDesignPatterns
GLOBALS
System Panic
27
Handle work assigned by the facade object. Have no knowledge of the facade; that is, they keep no references to it.
CS211 ooDesignPatterns
28
Intent:
An Object-Level Example
aListBox aClient
director director
aFontDialogDirector aButton
director
Dene an object that encapsulates how a set of objects interact, rather than having the objects refer to each other explicitly. Motivation: Simpler model; components send messages to the manager who decides how to reroute them. Easier to evolve components, less special knowledge scattered around subsystem
anotherButton
director
CS211 ooDesignPatterns
29
CS211 ooDesignPatterns
30
A Class-Level Example
Structure: Object-Level
DialogDirector
ShowDialog() CreateWidget() WidgetsChanged(Widget)
director
Widget
Changed()
aColleague aColleague
mediator
director->WidgetsChanged(this)
mediator
aConcreteMediator
ListBox
GetSelection()
EntryField
SetText()
FontDialogDirector
CreateWidget() WidgetsChanged(Widget)
list
aColleague
mediator
field
aColleague
mediator
CS211 ooDesignPatterns
31
CS211 ooDesignPatterns
32
Structure: Class-Level
Mediator
mediator
Colleague
ConcreteMediator
CS211 ooDesignPatterns
33
each colleague knows who its mediator object is each colleague communicates with its mediator when it wants to send messages
CS211 ooDesignPatterns
34
Intent: Dene a one-to-many dependency between objects so that when one object changes state, all its dependents are notied and updated automatically. Motivation:
(Dis)Advantages:
A common side-eect of partitioning a system into a collection of cooperating classes is the need to maintain consistency between related objects.
CS211 ooDesignPatterns
35
You dont want to achieve consistency by making the classes tightly coupled, because that reduces their re-usability.
CS211 ooDesignPatterns
36
Example of the Observer Pattern
a x y z b c a a b c b c
60 30 10 50 30 20 80 10 10
Subject
Attach(Observer) Detach(Observer) Notify()
The key objects in this pattern are subject and observer. A subject may have any number of dependent observers. All observers are notied whenever the subject undergoes a change in state.
observers
Observer Update()
CS211 ooDesignPatterns
change notification
requests, modifications
37
GetState() SetState() subjectState
ConcreteObserver
Update() subject return subjectState observerState observerState = subject->GetState()
ConcreteSubject
CS211 ooDesignPatterns
38
Notes:
after being informed of a change, Observer may query subject for more information
CS211 ooDesignPatterns
Maintains a reference to a concrete subject object. Stores state that should stay consistent with the subjects. Implements the updating interface.
39
can use abstract classes for Subject and Observer more exible, easier variation and composition ...
CS211 ooDesignPatterns
40
There are two basic models of updating: 1. push all observers notied whether they want the information or not
Flyweight Pattern
Intent: Use sharing to support large numbers of nely-grained objects eciently. Motivation: Some applications use lots of nely-grained (i.e., little) objects. BUT objects entail overhead (wrapping). If LOTS of such objects are required AND if such objects are really values at heart, then make a single pool of these objects for everyone to share.
2. pull subjects are sent little or no information (There has been a change; contact me for more details.) Might not want to push all of the information around to all observers: Not all objects need or ought to know everything. Message passing takes time, space, overhead. Some changes are undone or superuous
CS211 ooDesignPatterns
Subjects may register for only some kinds of information Have to specialize kinds of messages, more detail to manage.
41
CS211 ooDesignPatterns
42
Round and round the ragged rock the ragged rascal ran (apparently with no ill effects from the DDT on the grass). She sells sea shells by the sea shore; however, failure to disclose such earnings is a direct violation of federal income tax laws. Dont try this at home.
User text
row object
Representation
CS211 ooDesignPatterns
43
a b k u
d n x
e o y
f p z
h i s
j t
character objects
l m v w
q r
CS211 ooDesignPatterns
44
Glyph
Draw (Context) Intersects (Point, context)
children children
Row Character
Draw (Context) Intersects (Point, context) char c
Column
Draw (Context) Intersects (Point, context)
Could have separate object pool for each font family, pass in locations, size, slant, text colour to drawChar Allows for exible font family hierarchies rather than monolithic character class Call yweight because each object stores minimal information about its state
Notes:
letter-objects cannot (easily) have back references to the containing object When it comes time to draw the character, will have to pass in appropriate context that would normally be part of the object state e.g., (x, y ) screen locations, font information, text colour
CS211 ooDesignPatterns
45
CS211 ooDesignPatterns
46
FlyweightFactory
getFlyweight(key)
flyweights
Flyweight
Operation (extrinsicState)
ConcreteFlyweight1
Operation (extrinsicState) intrinsicState
ConcreteFlyweight2
Operation (extrinsicState) intrinsicState
declares an interface through which yweights can receive and act on extrinsic state Concrete Flyweight (Character) implements the Flyweight interface and adds storage for intrinsic state (if any).
Client
CS211 ooDesignPatterns
if (flyweight[key] exits) { return existing flyweight } else { create new flyweight add it to the pool return a ref. to it }
47
An instance of this class must be sharable Any state it stores must be intrinsic
CS211 ooDesignPatterns
48
Flyweight Factory creates and manages Flyweight objects as needed might create all yweight objects at start or just as needed Client maintains references to yweights computes/stores extrinsic state of yweight objects
ensures sharing is done properly, provides (and sometimes creates) instances as requested
CS211 ooDesignPatterns
49
CS211 ooDesignPatterns
50
Notes on Flyweights
creation may be done once at initialization or as needed on the y need to manage context (extrinsic state) separately from the objects This is unnatural and awkward! Watch out for errors, funny assumptions, odd glue commonly done to manage system resources
% Probably wrong
Also, all Java scalars have corresponding wrapper classes (e.g., Integer.
CS211 ooDesignPatterns
51
CS211 ooDesignPatterns
52
Intent:
How its done in various programming languages: Lisp-y functional languages provide mapcar-like function to do this. Pass in a function as an argument. C/C++ allow function-as-arguments, but C++ also provides an iterator class in the STL Java does not allow function-as-arguments, but does an iterator construct called an Enumeration.
Provide a clean, abstract way to access all of the elements in an aggregate (container) without exposing the underlying representation. Also, moves responsibility for access and traversal to a separate iterator object.
Motivation:
Often want to say to a container (e.g., tree, graph, table, list, graphic), Apply f() to each of your objects. . Dont want to expose implementation details of the container AND want to allow multiple simultaneous traversals Create separate interface/class that provides simple hooks.
CS211 ooDesignPatterns
53
CS211 ooDesignPatterns
54
java.util.Vector (array with resizable bounds) denes a method called elements that returns an enumeration of the vector.
CS211 ooDesignPatterns
55
CS211 ooDesignPatterns
56
Structure of the Iterator Pattern
list
List ListIterator
First() Next() IsDone() CurrentItem() index
Iterator Denes an interface for accessing and traversing elements. ConcreteIterator Implements an iterator interface. Keeps track of the current position in the traversal of the aggregate. Aggregate Denes an interface for creating an iterator object.
...
CS211 ooDesignPatterns
57
ConcreteAggregate Implements the iterator creation interface to return an instance of the proper concrete iterator.
CS211 ooDesignPatterns
58
Can have multiple iterations ongoing simultaneously (enumerator state basically consists how far along it is in the list). Of course, if you change (or allow others to change) the aggregate (add/remove) or its contained objects, then chaos may result! May therefore want to lock out changes during an iteration (concurrency control) iterator may take fast snapshot of aggregate state and use that to iterate through may want to buer requested changes while an iterator is active, then commit
CS211 ooDesignPatterns
59
Complicated structures may be dicult to iterate through Store path taken or nodes visited
CS211 ooDesignPatterns
60
};
Intent: Dene the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redene certain steps of an algorithm without changing the algorithms structure. Motivation: By dening some of the steps of an algorithm using abstract operations, the template method xes their ordering.
class Vehicle { private: char *plate; protected: virtual char *group () = 0; public: Vehicle () {plate=NULL;} Vehicle (char *p) { plate = new char [strlen(p)+1]; strcpy (plate, p); } virtual ~Vehicle () {delete [] plate;} virtual void identify () { char *p = plate ? plate : "<none>"; printf ("%s with plate %s\n", group(), p); }
CS211 ooDesignPatterns
Provide the skeleton of a method, where parts are dened/overridden by derived classes.
61
// Define similarly for Truck class Car : public Vehicle { private: char *group () {return "Car";}; public: Car () : Vehicle () {} Car (char *p) : Vehicle (p) {} };
CS211 ooDesignPatterns
62
AbstractClass
TemplateMethod()
...
PrimitiveOp1()
... ...
PrimitiveOp1() PrimitiveOp2()
PrimitiveOp2()
ConcreteClass
CS211 ooDesignPatterns
PrimitiveOp1() PrimitiveOp2()
63
Implements the primitive operations to carry out subclass-specic steps to the algorithm.
CS211 ooDesignPatterns
64
Notes on the Template Method Pattern
Very common to have in abstract base classes, esp. libraries intended for reuse and customization. A kind of polymorphism (think about it) practised within a class hierarchy. Whatever object I turn out to be, use my denition on primitiveOp(), then print, ... This is a common pattern to recognize during secondary passes at design.
Intent:
Without violating encapsulation, capture and externalize an objects internal state so that the object can be restored to this state later. Motivation: Often want to be able to take snapshots of an objects current state in case: want to unroll changes debugging store sequence of abstract transactions by class that is not privy to underlying representation of transaction.
CS211 ooDesignPatterns
state
Refactor commonalities into the parent class; push as much as possible as high as possible.
65
BUT dont want to break encapsulation/information hiding state type must be opaque
CS211 ooDesignPatterns
66
Originator
SetMemento (Memento m) CreateMemento()
Memento
GetState() SetState() state
Caretaker
Stores internal state of the Originator object. The memento may store as much or as little of the originators internal state as necessary at its originators discretion. Protects against unwanted access by objects other than the Originator. Eectively has two interfaces: narrow and wide Originator
state = m->getState();
CS211 ooDesignPatterns
67
Creates a memento containing a snapshot of its current internal state. Uses the memento to restore its internal state.
CS211 ooDesignPatterns
68
Caretaker is responsible for the mementos safekeeping. never directly operates on or examines the contents of a memento.
CS211 ooDesignPatterns
69
CS211 ooDesignPatterns
70
Intended to provide a common: vocabulary for inter-developer communication. set of abstract building blocks for system designers set of patterns to look for when refactoring / redesigning / reverse engineering existing systems. Not exclusively OO, despite the book title; really based on encapsulation and interacting objects. Seems particularly useful for concurrent/distributed systems where logic is hard to get right and possibilities are too numerous. Early days yet, but many are very excited.
CS211 ooDesignPatterns
71