Design Patterns by Eric Gamma...
** Design Patterns
- ~ capture solutions that have developed and evolved over time
- ~ makes it easier to use successful designs and architectures
- "Pattern" describe a problem that occurs over and over again in our
- ~ are description of communication objects and classes that are
customized to solve a general design problem in a particular context.
- Creational design patterns abstract the instantiation process. They
help make a system independent of how its objects are created, composed
and represented. Class creation pattern use inheritance where as object
creational pattern uses delegation.
- Structural patterns are concerned with how classes and objects are
composed to form larger structures. It describes ways to compose
objects to realize new functionality. It has the ability to change
composition at runtime.
- Behavioral Pattern: are concerned with algorithm and assignments of
responsibilities between objects. Patterns of communication, complex
control flow. Behavioral class pattern: Use inheritance to distribute
behavior between classes. Behavioral object pattern: Use object
** Creational Pattern: Abstract Factory
- Provides an interface for creating families of related or dependant
object without specifying their concrete classes
- Used to create multiple objects
- Applicability: Use ~ when:
- a system should be independent of how its products
are creates, composed, and represented
- a system should be constructed with one of
multiple families of products
- a family of related product objects is designed to
be used together and you need to enforce this constraint
- you want to provide a class library of products,
and u want to reveal just their interfaces, not their implementation.
- ~ defers creation of product objects to its concrete sub class(es)
- Consequences: ~ has the following benefits and liabilities:
- It isolates clients from implementation classes.
Clients manipulate instances through their abstract interfaces.
- It makes exchanging product families easy. It can
use different product configuration just by changing the concrete
- Promotes consistency among products
- Supporting new kind of products is difficult, as
interface is fixed
- Implemented as a singleton
- Abstract factory and concrete factory maybe the same class for small
** Creational Pattern: Builder
- Separate the construction of a complex object from its
representation, so that the same construction process can create
- Used to create a single object
- The class constructing the object different from the object's class
and is contained in the object's class. Actual construction work is
delegated to a sub class of the constructing class.
- Applicability: Use the ~ pattern when,
- the algorithm creating a complex object should be
independent of the parts that make up an object and how they are
- the construction object must allow different
representations of the object that's constructed
- lets you vary the product's internal representation
- isolates code for construction and representation
- gives you finer control over the construction
** Creational Pattern: Factory Method
- Define an interface to create an object but let the subclass decide
with class to instanciate. ~ lets a class defer instantiation to its
- Used to create a single object
- Applicability: Use ~ when
- a class can't anticipate the class of objects it
- a class wants its sub classes to specify the
object it creates
- classes delegate responsibility to one of several
helper sub classes, and you want to localize the knowledge of which
helper subclass is the delegate
- Provides hooks for subclasses
- Connects parallel class hierarchies: Used to
create and implement frameworks
- Clients may have to sub classes just for creation
** Creational Pattern: Prototype
- Specify the kinds of objects to create using a prototypical instance
and create new objects by copying this prototype
- To be used as a prototype, an object must support a copy constructor
and a "clone" operation
- Applicability: Use the ~ pattern when a system should be independent
of how its products are created, composed, and represented; and
- when the classes to instantiate are specified at
run time, eg. dynamic loading
- to avoid building a class hierarchy of factories
that parallels the class hierarchy of products
- when instances of a class can have one of only a
few different combinations of state.
- Adding and removing products at run time
- Specifying new objects by varying values
- Specifying new objects by varying structure
- Reduced subclassing
- Configuring an application with classes dynamically
** Creational Pattern: Singleton
- Ensure a class has only one instance and provide a global point of
access to it
- Applicability: Use a ~ pattern when
- there must be exactly one instance of a class and
it must be accessible to clients from a well known access point
- when the sole instance should be extensible by
subclassing, and clients should be able to use an extended instance
without modifying their code
- Controlled access to sole instance
- Reduced name space: ~ is an improvement over
- Permits refinement of operations and representation
- Permits a variable number of instances: can be
used in pooling
- More flexible than class operations.
** Structural Pattern: Adapter (Also known as wrapper)
- Convert the interface of a class into an interface clients expects.
- Applicability: Use Adapter pattern when:
- You want to use an existing class and its
interface does not match the one you need.
- You want to create a usable class that co-operates
with unrelated or unforeseen classes.
- You need to use several existing subclasses, but
its impractical to adapt their interface by sub-classing every one. An
object adapter can adapt the interface of its parent class.
- Adaption can be done by inheritance (class adaption) or composition
A class adapter
- won't work when we want to adapt a class and all
- lets adapter override some of adaptee's behavior
- introduces only one object and no additional
pointer indirection is needed.
An object adapter
- supports lots of single adapter
work with many adaptee's, i.e. complete hierarchy.
- makes it harder to override
- Other issues:
- how much adaption does adapter do ?
- plug-able adapter: interface adaption lets us
incorporate our class into existing system that might expect different
interface to the class i.e. we build of class(es) such that user might
be able to plugin their classes / objects into our class(es).
- 2 way adapters: an adapted *object* no longer
confirms to an adaptee's interface, so it cannot be used as is wherever
an adaptee's object can. 2 way adapters can provide this transparency.
Specifically, they are useful when 2 different clients need to view an
object differently. Usually implemented through multiple inheritance.
- In C++, adapter derives publicly from the target
and privately from the adaptee. If using object adapter, derive
publicly from the target and contain the adaptee.
** Structural Pattern: Bridge
- De-couple an abstraction from its implementation so that both can be
- Inheritance binds an implementation to the abstraction permanently,
which makes it harder to modify, extend, reuse abstraction and
- Applicability: Use bridge pattern when:
- You want to avoid permanent binding between
abstraction and its implementation. This might be the case when
implementation has to be selected / switched at runtime.
- Both abstraction and implementation should be
extensible via sub-classing. The bridge pattern lets you combine
different abstraction and implementation.
- changes in implementation of an abstraction should
have no effect on the client, i.e. no re-compiling.
- (C++ only) You want to hide the implementation of
an abstraction completely from the client.
- You want to share an implementation among multiple
objects, and this fact should be hidden from the client.
- Implementation is not bound permanently to its
- Improved extensibility
- Hiding implementation details from the client.
** Structural Pattern: Composite
- Compose objects into tree structures (class / object hierarchies) to
represent part-whole hierarchies. Composite pattern lets clients treat
individual objects and composition of objects uniformly.
- Applicability: Use composite pattern when:
- You want to represent part-whole hierarchies.
- You want the clients to be able to ignore the
differences between compositions of objects and individual objects.
- recursively defines class hierarchies consisting
of primitive and composite objects.
- makes clients simple: clients can treat all types
of objects in a similar manner
- makes it easier to add new types of components
- can make your design overly general
** Structural Pattern: Decorator
- Attach additional responsibilities to an object dynamically.
- Provides a flexible alternative to subclassing.
- Useful for adding responsibilities to objects rather than class (all
- Achieved by enclosing the object in a decorator.
- Decorators can be nested recursively.
- Applicability: Use decorator pattern:
- add responsibilities to individual objects
dynamically and transparently.
- for responsibilities that can be withdrawn.
- when extension by sub classing is impractical.
- A decorator is itself a component and also contains a component to
- more flexibility than static inheritance.
- avoid feature laden classes high up in the
- a decorator and its component aren't identical
- lots of little objects: can be heard to learn,
** Structural Pattern: Facade
- Provides a unified interface to a set of interfaces in a sub system.
- Facade defines a higher level interface that makes the sub system
easier to use.
- Applicability: Use facade pattern when:
- you want to provide a simple interface to a
complex sub system
- you need to de-couple the sub system from clients
and other sub systems, promoting sub system's independence and
- you want to layer your sub systems
- Shields clients from sub system components, there
by reducing the number of objects the client deals with, making the sub
system easier to use.
- promotes weak coupling between sub system and
client: you can vary components without affecting its client.
- simplifies porting sub systems to other platforms
** Structural Pattern: Flyweight
- Use sharing to support large number of fine grained objects
- Used to reduce the total number of objects in a system
- A flyweight is a shared object that be used in multiple contexts
simultaneously. The flyweight acts as an independent object in each
context. It is indistinguishable from an object that is not shared.
- Flyweight cannot make assumptions about the context in which they
- The key concept here is the distinction between intrinsic and
extrinsic state. Intrinsic state is stored in the flyweight and is
independent of the flyweight's context, thereby making it shareable.
Extrinsic state depends on and varies with the flyweight's context and
therefore can't be shared. Client objects are responsible for passing
the extrinsic state to the flyweight as an when needed.
- Intrinsic state is stored in the flyweight, extrinsic state is stored
or computed by client objects and is passed to the flyweight as and
when needed. (i.e. when a client invokes a flyweight operation needing
the extrinsic state).
- The flyweight interface enables sharing, not enforces it: A flyweight
subclass need not be shareable.
- The flyweight pattern is often combined with composite pattern to
represent a hierarchic structure with a graph, with shared leaf nodes.
- Applicability: Use flyweight pattern when all the following are true:
- an application uses a large no. of objects
- storage costs are high because of the sheer number
- most object state can be made extrinsic
- many groups of objects can be replaced with
relatively few shared objects once extrinsic state is removed.
- the application doesn't need to depend upon object
identity: Since flyweight objects can be shared, identity tests will
return true for conceptually distinct objects.
- Trade off between speed and storage.
- Storage saving are a function of several factors:
- The reduction in total number
of objects that come from sharing
- The amount of intrinsic state
- whether extrinsic state is
computed or stored.
** Structured pattern: Proxy (also known as Surrogate)
- Provide a surrogate or place holder for another object to control
access to it.
- One reason for controlling access to an object is to defer full cost
of its creation and its initialization until we actually need to use
it: create expensive objects on demand.
- The proxy and the "real subject" derive from the same class
- Copy on write: copying a large or complicated object can be an
expensive operation. If the copy is never modified, there is no need to
incur this cost. By using a proxy to postpone the copying process, we
ensure that we pay the price of copying only if it is modified. To make
this work, the subject must be reference counted.
- Overloading "->" operation in C++, can be used in the proxy object
to dynamically create the target.
- Applicability: A proxy is applicable whenever there is a need for
more versatile or sophisticated reference to an object than a simple
- A remote proxy provides a local representation for
an object in a different address space
- A virtual proxy creates expensive objects on demand
- A protection proxy controls access to the original
object. Useful when objects should have different access rights.
- A smart reference is a replacement for a bare
pointer that performs additional actions when an object is accessed.
** Behavioral Pattern: Chain of responsibility
- Avoid coupling the sender of a request to its receiver by giving more
than one object a chance to handle the request. Chain the receiving
objects and pass the request along the chain until an object handles it.
- Implemented by inheritance: message keeps getting passed to parent
until it is handled. Can also be implemented by composition.
- Applicability: Use ~ pattern when:
- more than one object may handle a request and the
handler is located dynamically
- u want to issue a request to several objects
without specifying the receiver explicitly.
- the set of objects that can handle a request
should be specified dynamically.
- reduced coupling
- added flexibility in assigning responsibility to
- receipt isn't guaranteed: the request can fall off
the end of the chain, without ever being handled
** Behavioral Pattern: Command (also known as Action, Transaction)
- Encapsulate the request as an object, thereby letting, you
parameterize clients with different requests, queues or log requests
and support within "undo"able operation.
- Applicability: Use ~ pattern when you want to:
- parameterize object by an action to perform
- specify queue and execute requests at different
- support undo
- support logging changes so that they can be
reapplied in case of a system crash
- structure a system around high level operation
built on primary operation
- Command de-couples the object that invokes the
operation from the one that knows how to perform it.
- Commands are first class objects
- Commands can be assembled into a composite command
- It is easy to add new commands as you don't have
to change existing classes
** Behavioral Pattern: Interpreter
- Given a language, define a representation for its grammar, along with
an interpreter that uses the representation to interpret sentences in a
- Applicability: Use ~ pattern when there is a language to interpret
and you can represent statement in a language as abstract syntax trees.
The interpreter pattern works best when:
- the grammar is simple. For complex grammar, the
class hierarchy for the grammar becomes large and unmanageable. Tools,
such as parser generation, are better in such cases.
- efficiency is not a critical concern
- It is easy to change and extend the grammar
- Implementing the grammar is easy too
- Complex grammar is hard to maintain
- Easier to evaluate an expression in a new way
** Behavioral Pattern: Iterator (Also known as cursor)
- Provide a way to access the elements of an aggregate object
sequentially without exposing its underlying representation.
- The object being traversed has to have the knowledge of which
iterator would be best suited for itself. Hence the method to create an
iterator for an object is contained in the object itself. The factory
pattern could be used for such an implementation.
- Applicability: Use iterator pattern:
- to access an aggregate object's contents without
exposing its internal representation
- to support multiple traversal of aggregate objects
- to provide a uniform interface for traversing
different aggregate structures (polymorphic iteration)
- Support variation in traversal of an aggregate
- iterator simplifies the aggregate interface
- more than one traversal can be pending on an
** Behavioral Pattern: Mediator
- Define an object that encapsulates how a set of object interact
- ~ promotes loose coupling by keeping objects from referring each
other explicitly, and it lets you vary their interaction independently.
- ~ serves as an intermediary and reduces the number of interconnection
- The behavior is located in one class. It can be changed or replaced
by extending or replacing that class
- Facade differs from ~ in that it abstracts a sub system of objects to
provide a more convenient interface. Its protocol is unidirectional.
- Applicability: Use ~ when:
- a set of objects communicate in well defined but
complex ways. The resulting independencies are unstructured and
difficult to understand
- reusing an object is difficult because it refers
to and communicates with many other objects.
- a behavior that is distributed between several
classes should be customizable without a lot of sub-classing
- reduced sub classing
- de-couples colleagues - objects that interact
- simplifies object protocol
- abstracts how objects cooperate
- centralizes control: increases complexities of
mediator, which can become hard to maintain.
** Behavioral Pattern: Memento (also known as token)
- Without violating encapsulation, capture & externalize an
object's internal state, so that the object can restore to this state
- A ~ is an object that stores a snapshot of the internal state of
another object (the memento's originator)
- The originator initializes the memento with information that
characterizes its current state.
- Only the originator can store and retrieve information from the
memento: the memento is opaque to other objects
- Applicability: use ~ when
- a snapshot of (or some portion of) an object's
state must be saved so that it can be restored to that state later, and
- a direct interface to obtaining the state would
expose implementation details and break the objects encapsulation.
- Preserving encapsulation boundaries
- simplifies originator
- using ~ might be expensive: copy of large objects
- defining narrow and wide interfaces
- hidden costs of caring for mementos: caretaker
** Object Behavioral Pattern: Observer (Also known as dependents,
- Define a one to many dependency between objects so that when one
object changes state, all its dependents are notified and updated
- By encapsulating complex update semantics, the change manager can act
as mediator between subjects and observer.
- Applicability: use ~ in any of the following situations
- when an abstraction has 2 aspects: one dependent
on the other. Encapsulating these objects into separate objects lets
you vary and use them independently.
- when a change to one object requires changing
others and you don't know how many objects need to be changed.
- when an object should be able to notify other
objects without making assumption about who those objects are. In other
words, you don't want these objects tightly coupled
- Abstract coupling between subject and observer
- support for broadcast communication
- unexpected updates
** Object Behavioral Pattern: State (Also known as objects for state)
- Allows an object to alter it behavior, when its internal state
changes. The object will appear to change its class.
- An object maintains a state variable that changes its instance
(class) when the state of the object changes.
- All requests are delegated to the state object.
- The state object is itself responsible for changing its state,
usually through call backs.
- Applicability: Use ~ in either of the following cases:
- An object's behaviors depends on its state and it
must change its behavior at run-time depending on its state.
- Operations have large multipart conditional
statements, that depend on the object's state.
- ~ localizes state specific behavior and partitions
behavior from different states.
- makes state transition explicit
- state objects can be shared, if state objects have
no instance variables: similar to flyweight
** Object Behavioral Pattern: Strategy (Also known as Policy)
- Define a family of algorithms, encapsulate each one, and make them
interchangeable. ~ lets the algorithm vary independently from the
clients that use them.
- Applicability: Use ~ when
- many related classes differ only in behavior.
Strategy provides a way to configure a class with one of many behaviors.
- u need different variants of an algorithm
- an algorithm uses data that a client should not
- a class defines many behaviors and these appear as
multiple conditional statements in its operation.
- Families of related algorithms: inheritance can
help factor out common functionalities of the algorithms.
- An alternate to subclassing
- Strategies eliminate conditional statements.
- Choice of implementation: can provide different
implementation of the same behavior.
- clients must be aware of different strategies
- communication overhead between strategy and context
- Increased number of objects
** Class Behavioral Pattern: Template Method
- Define the skeleton of an algorithm in an operation, deferring some
steps to subclasses. Template method lets subclasses re-define certain
steps of an algorithm without changing the algorithm's structure.
- ~ is a fundamental technique for code re-use.
- Control is in the parent class. Parent class calls the operations of
a subclass, not the other way around.
- Applicability: Use ~,
- to implement parts of an algorithm once and leave
it upto subclasses to implement the behavior that can vary.
- when common behavior among subclasses should be
factored and localized in a common class to avoid code duplication.
- to control sub class extensions. You can define a
template method that calls "hook" operation at specific points and
there by permitting extensions only to those points.
- Consequences: template methods call the following kinds of operations:
- concrete operations: either on concrete class or
- concrete abstract class operations
- primitive operations (abstract operations)
- factory methods
- hook operations
** Object Behavioral Pattern: Visitor
- Represents an operation to be performed on the elements of an object
- ~ lets you define a new operation without changing the classes of the
elements on which it operates.
- With ~, you define 2 class hierarchies: one for the elements being
operated and one for the visitors that define operations on these
elements. You can create a new operation by adding a new subclass to
the visitor class hierarchy.
- Visitor will need to define a "visit" operation for each class of
element in the object structure. Visitor will invoke a method that will
call back the corresponding visit operation for itself.
- Applicability: Use ~:
- when, an object structure contains many classes of
objects with differing interfaces and you want to perform operations on
these objects that depend on their concrete classes.
- when, many distinct and unrelated operations need
to be performed on objects in an object structure, and u want to avoid
polluting their classes with these operations.
- when, the classes defining the object structure
rarely changes, but you often want to define new operations over the
structure. Changing the object structure classes require redefining the
interface to all visitors, which is potentially costly.
- to do interpretation.
- Visitors make adding new operation easy.
- A visitor gathers related operation and separates
- Adding new concrete element subclass is hard:
requires modification to a large number of visitors.
- Visitors can visit across class hierarchies vs
iterator that work with only one type of class.
- visitors can accumulate state
- Breaking encapsulation: Visitors often force you
to provide public operations that access element's internal state,
which may compromise its encapsulation.
- Read Chapter 2 again after completing book
- Reread Structure and participants for each pattern
- Give the author feedback: Prototype pattern.