The editor example in your text gives a good summary of several patterns
along with illustrations of how they are applied.
Here is another summary of patterns, organized into several categories,
with the context and structure of each each briefly explained.
Solutions to the problem that when you define an abstract interface
and then subclass it with concrete classes, there are no constructors
for the concrete classes that can be invoked from the abstract interface.
Separate factory class, typically named after the interface class,
containing one or more methods eahc of which returns an instance of a
concrete class that implements the interface.
- Abstract Factory
Multiple factories (builders) to create different categories of objects.
Make an abstract class to provide general abstract interface for
several related factories. Provide concrete subclasses for the
- Factory Method
Implement a factory without making a separate class... merge the
factory class into an existing class. Do this when factory class
flexibility is not needed, when an appropriate class to merge with
is obvious, and when factory methods are few.
This pattern allows the factory method(s) to be inherited.
Used to create only one object instance of a class. Keeps track of
whether the constructor has been invoked, and once invoked, subsequent
constructor invocations are trapped and the existing pointer
returned for the singleton object.
Often used to create factory classes... since there needs be only
one builder of each type. Also can be used to create global
data as object storage.
Useful when application needs to share objects; helps prevent
big proliferation of small objects, like nodes in an expression
tree. Implemented as hash table (for example) of pointers to
singleton objects. Also used for character (glyph) objects
in text editors, etc.
Does not use classes... instead uses prototype objects and clones them.
Ask existing prototype object to close itself when a new object of
that class is needed.
Patterns for effectively using delegation to replace inheritance.
Inheritance is static and hence lacks flexibility; delegation is
dynamic and allows alterations at run-time.
Delegation is passing responsibility for an activity from one object
The object doing to delegation must maintain a pointer to the object
receiving the delegation. Each operation being delegated must be
correctly coded to invoke a corresponding operation in the object
C++ does not provide explicit support for all these mechanics as
some newer OO languages do.
Use when the functionality needed for some class is already provided
in another existing class. The interfaces need to be brought into
synch. Often used to have a windowing class written specifically
in application terms, but then to be implemented by delegation
to some common windowing package (X, Motif, etc.).
For separating an interface from its implementation.
A bridge is a wrapper, a class that completely contains the
interface to another class. There is no way to get to the
wrapped class except "across the bridge" class. Continuing
the analogy, the wrapped class is an island, unreachable
except by the bridge.
Chain of bridges... components of the chain can be altered
during execution to respond to user functionality selections.
Each object in the decorator chain must have the same interface
as the object being decorated.
Each object adds some functionality or "decoration" to the base object,
and this decoration can be dynamically added or subtracted
(unlike if this were done via inheritance).
Combination of delegations. A wrapper object that maintains multiple
pointers to other objects, the combination of which provide the
functionality of the wrapper. So the facade has an interface
that is partially provided by each object to which it delegates
An object that can stand in the place of another object and field
requests for the methods of the wrapped object; a proxy can even
stand in for an object that does not (yet) exist at the time
its methods are invoked. Allows creation of the wrapped object
at some future time, when it becomes truly necessary.
For example, in an editor, there may be numerous graphic objects
for the drawing, pictures, etc. in a document. There is no need
to incur the run-time expense of creating these graphic objects
(and loading them with extensive data from disk) if they are not
visible on the screen. So cheaper proxys can be generated for the
graphics to hold open a place in the document until one needs to
be displayed. Then the proxy can trigger creation and loading
of the object for which it is fronting.
Proxies are also commonly used in distributed systems to encapsulate
the behavior and interface of a remote server. The proxy in this case
differs from a "standard" wrapper in that it will be responsible
for the extra detail of creating remote network calls... and the client
can talk to the proxy as if it were a local object, simplifying
the client code by the labor division.
For creating well organized hiearchies of related objects, in such a
way that atomic objects and composites of those atomics can be
treated uniformly by a client. For example, in a graphics program,
a grouping of shapes should be able to be an element in a drawing
just as a single shape... and hence, a grouping could be an
element in another grouping. So a composite pattern allows
an object that can represent a shape or a grouping uniformly.
Somewhat specialized pattern.
Encapsulation of an algorithm for processing a specialized data structure,
usually a grammar for a language.
For example, in a compiler, a syntax tree might be processed
by an interpreter pattern that knows how to manipulate that tree to
determine the code to be generated from the syntax.
Iterator is a specialized form of Interpreter. Its purpose is to
traverse a data structure and produce in some sequence all the
elements of the structure. The pattern allows this traversal
by clients without them having to know the internal structure
of the data.
For encapsulating a user interface so that user sessions can be
"traversed" (i.e., undo, redo).
User commands are made concrete as data structures.
Allows the substitution of alternate forms of an algorithm, dynamically
selected for processing different forms of related data.
For example, in a text editor, when text needs formatting the user
might select pagenated, or hypehnated, or neither... requiring
three slightly different algorithms. Instead of having lots of
conditionals in one big formatting algorithm, three
slightly different ones can be written and encapsuated in
objects that are delegated to at run-time.
Uses inheritance to replace parameterized portions of an algorithm
at compile time...
in contrast to Strategy, which uses dynamic delegation to replace entire
algorithms at run-time.
The template is a concrete method in an abstract class; it invokes
abstract methods that are given different concrete realizations
by subclassing, thus fleshing out the algorithm template in different
ways for different subclasses.
Often used with an Iterator. Visitor object encodes the logic for
handling different kids of nodes in a data structure... as Iterator
walks a structure, each node the visitor "calls on" the node and
processes the data.
Manages interaction of collection of objects.
Promotes loose coupling by keeping objects that need to interact
from referring to each other directly by pointers.
Mediator object encodes the interactions that are allowed,
manages object references.
Could be useful for collaborative distributed systems, where
various interaction rules control how users may collaborate.
One use is for dialog boxes in user interfaces. Mediator object keeps
track of all the buttons and widgets in the box, and directs data
from one to the other. That way, the widgets do not need to be aware
of each other, and they can come and go from the interface dynamically.
An object that can snapshot the internal state of another object
(makes a mememto of that object); memento object understands the
internal structure, but the various clients that need the
snapshots do not have to know the internal structure of the object.
Defines a one-to-many dependencies structure among objects.
Allow changes in one object to cause propogated changes in the
related objects. Used in model-view-controller structures
to manages different simultaneous views of data. For example,
in a spreadsheet you might have a barchart representation of
data in cells, a piechart, and the numerical cells. All need to
be updated as the numbers change.
The observer will watch for changes in one and trigger corresponding
actions in the related objects.