Professional Documents
Culture Documents
Pat
Pat
com/design_patterns ************* */
A design pattern is a general solution to a commonly occurring problem in softwa
re design.
Creational design patterns
-------------------------These design patterns are all about class instantiation. This pattern can be fur
ther divided into class-creation
patterns and object-creational patterns. While class-creation patterns use inher
itance effectively in the
instantiation process, object-creation patterns use delegation effectively to ge
t the job done.
* Abstract Factory------Creates an instance of several families of classes
* Builder----------Separates object construction from its representation
* Factory Method
Creates an instance of several derived classes
* Object Pool
Avoid expensive acquisition and release of resources by recyclin
g objects that are no longer in use
* Prototype-------A fully initialized instance to be copied or cloned
* Singleton-------A class of which only a single instance can exist
Structural design patterns
-------------------------These design patterns are all about Class and Object composition. Structural cla
ss-creation patterns use inheritance
to compose interfaces. Structural object-patterns define ways to compose objects
to obtain new functionality.
* Adapter--------Match interfaces of different classes
* Bridge
Separates an object s interface from its implementation
* Composite
A tree structure of simple and composite objects
* Decorator
Add responsibilities to objects dynamically
* Facade
A single class that represents an entire subsystem
* Flyweight
A fine-grained instance used for efficient sharing
* Private Class Data
Restricts accessor/mutator access
* Proxy
An object representing another object
Behavioral design patterns
-------------------------These design patterns are all about Class's objects communication. Behavioral pa
tterns are those patterns that
are most specifically concerned with communication between objects.
* Chain of responsibility
A way of passing a request between a chain of objects
* Command
Encapsulate a command request as an object
* Interpreter
A way to include language elements in a program
* Iterator------Sequentially access the elements of a collection
* Mediator
Defines simplified communication between classes
* Memento
Capture and restore an object's internal state
* Null Object
Designed to act as a default value of an object
* Observer--------A way of notifying change to a number of classes
* State
Alter an object's behavior when its state changes
* Strategy
Encapsulates an algorithm inside a class
* Template method
Defer the exact steps of an algorithm to a subclass
* Visitor--------Defines a new operation to a class without change
================================================================================
====================================
-------------------------------------------------Singleton--------------------------------------------------------================================================================================
====================================
The singleton pattern ensures a class has only one instance, and provides a glob
al point of access to it.
It makes use of private constructor, static/ class method and private static var
iable.
* Singleton class manages single instance itself. It prevents other class from c
reating a new instance by declaring
its constructor private.To get an instance class method needs to be called.
* It provides global point of access to instance by providing a class method get
Instance() to get the instance.This
method is the only way to get singleton class instnce.
* This method also provides lazy instantiation of singleton.
* The advantage of Singleton over global variables is that you are absolutely su
re of the number of instances when
you use Singleton, and, you can change your mind and manage any number of inst
ances. Also lazy instantiation
can be done in singleton.
example :
class singleton
{
private :
static singleton *uniqueInstance;
singleton(){}
public :
static singleton* getInstance()
{
// Lazy instantiation : creating an object when it is required t
o be used, not up-front.
if(uniqueInstance == NULL)
class StackIter
{
// 1. Design an "iterator" class
const Stack *stk;
int index;
public:
StackIter(const Stack *s)
{
stk = s;
}
void first()
{
index = 0;
}
void next()
{
index++;
}
bool isDone()
{
return index == stk->sp + 1;
}
int currentItem()
{
return stk->items[index];
}
};
StackIter *Stack::createIterator()const
{
return new StackIter(this);
}
================================================================================
====================================
-------------------------------------------------Composite--------------------------------------------------------================================================================================
====================================
* Compose objects into tree structures to represent whole-part hierarchies. Comp
osite lets clients treat individual
objects and compositions of objects uniformly.
* It allows us to build tree structure of objects that contains both composition
of objects and objects as node.
* Using this we can apply same operations over both.
* Manipulate a hierarchical collection of "primitive" and "composite" objects. P
rocessing of a primitive object is
handled one way, and processing of a composite object is handled differently
Example :
* Menus that contain menu items, each of which could be a menu.
* Directories that contain files, each of which could be a directory.
Implementation :
* Define an abstract base class (Component) that specifies the behavior that nee
ds to be exercised uniformly across
all primitive and composite objects. Subclass the Primitive and Composite clas
ses off of the Component class.
Each Composite object "couples" itself only to the abstract type Component as
Clients call methods on the Adapter object which redirects them into calls to
the legacy component. This strategy
can be implemented either with inheritance or with aggregation.
* Adapter functions as a wrapper or modifier of an existing class. It provides a
different or translated view of that
class.
Relation with other patterns :
* Adapter makes things work after they're designed; Bridge makes them work befor
e they are.
* Bridge is designed up-front to let the abstraction and the implementation vary
independently. Adapter is
retrofitted to make unrelated classes work together.
* Adapter provides a different interface to its subject. Proxy provides the same
interface. Decorator provides
an enhanced interface.
* Adapter is meant to change the interface of an existing object. Decorator enha
nces another object without changing
its interface. Decorator is thus more transparent to the application than an a
dapter is. As a consequence, Decorator
supports recursive composition, which isn't possible with pure Adapters.
* Facade defines a new interface, whereas Adapter reuses an old interface. Remem
ber that Adapter makes two existing
interfaces work together as opposed to defining an entirely new one.
Class Adaptors and Object Adapters :
--------------------------------* Class adapter uses inheritance, can also override behavior of adaptee. Object
adapter uses composition, also
adopts all the subclasses of adaptee
// Desired interface (Target)
class Rectangle
{
public:
virtual void draw() = 0;
};
// Legacy component (Adaptee)
class LegacyRectangle
{
public:
LegacyRectangle(int x1, int y1, int x2, int y2) {
std::cout << "LegacyRectangle(x1,y1,x2,y2)\n";
}
void oldDraw() {
std::cout << "LegacyRectangle: oldDraw(). \n";
}
};
// Adapter wrapper
class RectangleAdapter: public Rectangle, private LegacyRectangle
{
public:
RectangleAdapter(int x, int y, int w, int h):
LegacyRectangle(x, y, x + w, y + h) {
std::cout << "RectangleAdapter(x,y,x+w,x+h)\n";
}
void draw() {
std::cout << "RectangleAdapter: draw().\n";
oldDraw();
}
};
================================================================================
====================================
-------------------------------------------------Factory Method---------------------------------------------------================================================================================
====================================
* Define an interface for creating an object, but let subclasses decide which cl
ass to instantiate. Factory Method
lets a class defer instantiation to subclasses.
* Factory Method is to creating objects as Template Method is to implementing an
algorithm. A superclass specifies
all standard and generic behavior (using pure virtual "placeholders" for creat
ion steps), and then delegates the
creation details to subclasses that are supplied by the client.
* Factory Methods are routinely specified by an architectural framework, and the
n implemented by the user of the
framework.
* As with every factory, Factory method pattern gives us a way to encapsulate th
e instantiation of concrete types.
* An increasingly popular definition of factory method is: a static method of a
class that returns an object of that
class' type. But unlike a constructor, the actual object it returns might be a
n instance of a subclass. Unlike a
constructor, an existing object might be reused, instead of a new object creat
ed. Unlike a constructor, factory
methods can have different and more descriptive names
* The client is totally decoupled from the implementation details of derived cla
sses. Polymorphic creation is
now possible.
* If you have an inheritance hierarchy that exercises polymorphism, consider add
ing a polymorphic creation capability
by defining a static factory method in the base class.
* Design the arguments to the factory method. What qualities or characteristics
are necessary and sufficient to identify
the correct derived class to instantiate?
* Consider designing an internal "object pool" that will allow objects to be reu
sed instead of created from scratch.
* Consider making all constructors private or protected.
* Abstract Factory classes are often implemented with Factory Methods, but they
can be implemented using Prototype.
* Factory Methods are usually called within Template Methods.
* Factory Method: creation through inheritance. Prototype: creation through dele
gation.
* Often, designs start out using Factory Method (less complicated, more customiz
able, subclasses proliferate) and
evolve toward Abstract Factory, Prototype, or Builder (more flexible, more com
plex) as the designer discovers
where more flexibility is needed.
* The advantage of a Factory Method is that it can return the same instance mult
iple times, or can return a subclass
rather than an object of that exact type.
objects of several classes. Builder has the factory object building a complex
product incrementally using a
correspondingly complex protocol. Prototype has the factory object (aka protot
ype) building a product by copying
a prototype object.
* Factory method is used to implement concrete factories.
Problem
* If an application is to be portable, it needs to encapsulate platform dependen
cies. These "platforms" might include:
windowing system, operating system, database, etc.
Difference between factory and abstract factory :
---------------------------------------------* Both decouples implementation(creating object) from application. Decouples cli
ent from concrete classes
* Factory method uses inheritance(to override factory method) while abstract fac
tory uses object composition to
create objects.
================================================================================
====================================
-------------------------------------------------Visitor Design Pattern-------------------------------------------================================================================================
====================================
* Represent an operation to be performed on the elements of an object structure.
Visitor lets you define a new
operation without changing the classes of the elements on which it operates.
* The classic technique for recovering lost type information.
* Do the right thing based on the type of two objects.
* Double dispatch
* Visitor's primary purpose is to abstract functionality that can be applied to
an aggregate hierarchy of "element"6
objects. The approach encourages designing lightweight Element classes - becau
se processing functionality is removed
from their list of responsibilities. New functionality can easily be added to
the original inheritance hierarchy by
creating a new Visitor subclass.
* Visitor implements "double dispatch". OO messages routinely manifest "single d
ispatch" - the operation that is
executed depends on: the name of the request, and the type of the receiver.
In "double dispatch", the operation executed depends on: the name of the reque
st, and the type of TWO
receivers (the type of the Visitor and the type of the element it visits).
Implementation :
-------------* Create a Visitor class hierarchy that defines a pure virtual visit() method in
the abstract base class for each
concrete derived class in the aggregate node hierarchy. Each visit() method ac
cepts a single argument - a pointer
or reference to an original Element derived class.
* Each operation to be supported is modelled with a concrete derived class of th
e Visitor hierarchy. The visit() methods
declared in the Visitor base class are now defined in each derived subclass by
allocating the "type query and cast"
code in the original implementation to the appropriate overloaded visit() meth
od.
* Add a single pure virtual accept() method to the base class of the Element hie
rarchy. accept() is defined to receive
a single argument - a pointer or reference to the abstract base class of the V
isitor hierarchy.
* Each concrete derived class of the Element hierarchy implements the accept() m
ethod by simply calling the visit()
method on the concrete derived instance of the Visitor hierarchy that it was p
assed, passing its "this" pointer as
the sole argument.
* When the client needs an operation to be performed, (s)he creates an instance
of the Vistor object, calls the
accept() method on each Element object, and passes the Visitor object.
* The accept() method causes flow of control to find the correct Element subclas
s. Then when the visit() method is
invoked, flow of control is vectored to the correct Visitor subclass. accept()
dispatch plus visit() dispatch equals
double dispatch.
* The Visitor pattern makes adding new operations (or utilities) easy - simply a
dd a new Visitor derived class. But,
if the subclasses in the aggregate node hierarchy are not stable, keeping the
Visitor subclasses in sync requires
a prohibitive amount of effort.
Check list :
----------* Confirm that the current hierarchy (known as the Element hierarchy) will be fa
irly stable and that the public
interface of these classes is sufficient for the access the Visitor classes wi
ll require. If these conditions are
not met, then the Visitor pattern is not a good match.
* Create a Visitor base class with a visit(ElementXxx) method for each Element d
erived type.
* Add an accept(Visitor) method to the Element hierarchy. The implementation in
each Element derived class is always
accept( Visitor v ) { v.visit( this ); }. Because of cyclic dependencie
the same
s, the declaration of the Element
and Visitor classes will need to be interleaved.
* The Element hierarchy is coupled only to the Visitor base class, but the Visit
or hierarchy is coupled to each Element
derived class. If the stability of the Element hierarchy is low, and the stabi
lity of the Visitor hierarchy is high;
consider swapping the 'roles' of the two hierarchies.
* Create a Visitor derived class for each "operation" to be performed on Element
objects. visit() implementations
will rely on the Element's public interface.
* The client creates Visitor objects and passes each to Element objects by calli
ng accept().
* The abstract syntax tree of Interpreter is a Composite (therefore Iterator and
Visitor are also applicable).
* Iterator can traverse a Composite. Visitor can apply an operation over a Compo
site.
* The Visitor pattern is like a more powerful Command pattern because the visito
r may initiate whatever is appropriate
for the kind of object it encounters.
* The Visitor pattern is the classic technique for recovering lost type informat
ion without resorting to dynamic casts.
==========================================================
Strategy Pattern
==========================================================
The strategy pattern is intended to provide a means to define a family of algori
thms, encapsulate each one as an object,
and make them interchangeable. The strategy pattern lets the algorithms vary ind
ependently from clients that use them.
class SortBehavior
{
public:
virtual void sort() const = 0;
};
class Merge: public SortBehavior
{
public:
virtual void sort() const {
cout << "Merge sort()\n";
}
};
class Quick: public SortBehavior {
public:
virtual void sort() const {
cout << "Quick sort()\n";
}
};
class Heap: public SortBehavior
{
public:
virtual void sort() const {
cout << "Heap sort()\n";
}
};
class SearchBehavior
{
public:
virtual void search() const = 0;
};
class Sequential: public SearchBehavior
{
public:
virtual void search() const {
cout << "Sequential search()\n";
}
};
class BinaryTree: public SearchBehavior
{
public:
virtual void search() const {
cout << "BinaryTree search()\n";
}
};
class HashTable: public SearchBehavior
{
public:
virtual void search() const {
cout << "HashTable search()\n";
}
};
// Context
class Collection
{
private:
SortBehavior* m_sort;
SearchBehavior* m_search;
public:
Collection(){}
void set_sort(SortBehavior* s){
m_sort = s;
}
void set_search(SearchBehavior* s){
m_search = s;
}
void sort() const {
m_sort->sort();
}
void search() const {
m_search->search();
}
};
=====================================================================
Decorator Pattern
=====================================================================
Attach additional responsibilities to an object dynamically.
Decorators provide flexible alternatives to subclassing for extending functional
ity.
Let's take a look at code with the class diagram.
Each component (Window) can be used on its own, or wrapped by decorator.
The ConcreteComponent (SimpleWindow) is the object we're going to dynamically ad
d new behavior (vertical/horizontal scrollbars) to. It inherits Component.
class SimpleWindow : public Window
Each decorator has-a (wraps) a component, which means the decorator has an insta
nce variable that holds a pointer to a component.
class WindowDecorator : public Window
{
protected:
Window *m_decoratedWindow;
...
Decorators implement the same interface or abstract class as the component they
are going to decorate.
The ConcreteDecorator has an instance variable for the thing it decorate (the Co
mponent the Decorator wraps).
};
class BorderDecorator: public Decorator
{
public:
// 6. Optional embellishment
BorderDecorator(Widget *w): Decorator(w){}
/*virtual*/
void draw()
{
// 7. Delegate to base class and add extra stuff
Decorator::draw();
cout << " BorderDecorator" << '\n';
}
};
int main()
{
// 8. Client has the responsibility to compose desired configurations
Widget *aWidget = new BorderDecorator(new BorderDecorator(new ScrollDecorator
(new TextField(80, 24))));
aWidget->draw();
}
===========================================================================
Observer Pattern
===========================================================================
Observer Pattern's intent is to define a one-to-many dependency between objects
so that when one object changes state,
all its dependants are notified and updated automatically.
The subject and observers define the one-to-many relationship. The observers are
dependent on the subject
such that when the subject's state changes, the observers get notified. Dependin
g on the notification,
the observers may also be updated with new values.
class Subject;
class Observer
{
public:
Observer() {};
~Observer() {};
virtual void Update(Subject* theChangeSubject) = 0;
};
class Subject
{
public:
Subject() {};
virtual ~Subject() {};
virtual void Attach(Observer*);
virtual void Detach(Observer*);
virtual void Notify();
private:
vector<Observer*> _observers;
};
DigitalClock(ClockTimer *);
~DigitalClock();
void Update(Subject *);
void Draw();
private:
ClockTimer *_subject;
};
DigitalClock::DigitalClock (ClockTimer *s)
{
_subject = s;
_subject->Attach(this);
}
void DigitalClock::Update (Subject *theChangedSubject)
{
if(theChangedSubject == _subject)
Draw();
}
void
{
int
int
int
DigitalClock::Draw ()
hour = _subject->GetHour();
minute = _subject->GetMinute();
second = _subject->GetSecond();
OO Principles :
------------* Encapsulate what varies.
* Favor compostion over inheritance.
* Program to interface not implementation.
* Strive for loosely coupled designs between objects that interact.
* Classes should be close for modification open for extension.
* Depend on abstraction. Do not depend on concrete classes.
* A class should have only one reason to change.
* Identify the aspects that vary and seperate them from what stays same.
* Depend upon abstraction do not depend on concrete classes.((Abstract)Factory m
ethods)
Association, Aggregation, and Composition :
---------------------------------------* The IS A relationship : Inheritance
Example : Manager is an employee of XYZ limited corporation.
The sentence above specifies that Manager is a type of employee
* The Using relationship: Association
Example : Manager uses a swipe card to enter XYZ premises.
The manager object and the swipe card object use each other but they hav
e their own object life time.
In other words, they can exist without each other. There is no single owner
in this relationship.
Parent: Aggregation
who work under him.
of relationship like association but with a differ
object can have its own life time which is complet
Parent: Aggregation
who work under him.
of relationship like association but with a differ
object can have its own life time which is complet