The pattern schema, or rather a simplified version thereof, is depicted in slide pattern-schema. Each pattern must have a name, which acts as a handle in discussions about the design. Being able to speak about specific pattern solutions, such as a factory, greatly facilitates discussions about design.
In this section we will look at a brief overview
of the classification as originally presented in
See Pattern Lectures Creational patterns
Design for change means to defer commitment
to particular object implementations as long as possible.
Due to inheritance, or rather subtyping,
the client, calling a particular method,
can choose the most abstract class, highest in the hierarchy.
However, when it comes to creating objects,
there seems to be no other choice than naming
the implementation class explicitly.
Wrong.
Creational patterns are meant to take care of that,
that is to hide the actual class used as far away as possible.
Creational patterns
If you prefer a more dynamic approach, the prototype pattern might be better. A prototype is an object that may be used to create copies or clones, in a similar way as instances are created from a class. However, cloning is much more dynamic, the more so if delegation is used instead of inheritance to share resources with some ancestor class. See section prototypes.
The advantage of using a factory, or any of the other
creational patterns, is that exchanging product families
becomes very easy.
Just look for example at the Java Swing library.
Swing is supported under Unix, Windows and MacOS.
The key to multiple platform support is here, indeed,
the use of factories to create widgets.
Factories are also essential when using CORBA,
simply because calling a constructor is of no use
for creating objects on a remote site.
Closely related to the Composite pattern is
the Flyweight pattern, which is needed when
the number of components grows very large.
In that case, the components themselves must for obvious reasons
carry as little information as possible.
Context or state information must then be passed as a parameter.
To give some more examples, suppose there exists a
nice library for formatting text and images, but unfortunately
with only a procedural interface.
Then the Adaptor pattern may be used to provide
a interface that suits you, by wrapping the original library.
The Bridge pattern is in some sense related to the
Factory. In order to work with a platform-independent
widget library, you need, as has been explained, a factory
to hide the creation of widgets, but you also need to
bridge a hierarchy of platform-dependent implementation
classes to the more abstract platform-independent widget set.
When creating widgets to display text or images it may be very
inconvenient to create a separate class, for example
when adding scrolling functionality.
The Decorator pattern
allows you to insert additional functionality without subclassing.
Now think of a networked application, for example to be able
to incorporate components that are delivered by a server.
The library may provide a number of networking classes
that deal with all possible communication protocols.
To simplify access to these classes a Facade
may be built, hiding the complexity of the original
class interfaces.
Alternatively, remote components may be available
through a proxy.
The Proxy pattern describes how access may be regulated
by an object that acts as a surrogate for the real object.
Like composites and decorators, proxies
may be used for recursive composition.
However, proxies primarily regulate access,
whereas decorators add responsibilities,
and composites represent structure.
As an example of the Template Method pattern,
think of a compiler class that offers methods for
scanning and the creation of a parse tree.
Each of these methods may be refined without affecting the
structure of the compilation itself.
An interpreter allows for evaluating
expressions, for example mathematical formula.
Expressions may be organised in a hierarchy.
new kinds of expressions can be inserted simply by filling
in details of syntax and (semantic) evaluation.
Object composition, which employs the handle/body
idiom and delegation, is employed in
the Mediator pattern,
the Chain of Responsibility pattern
and the Observer pattern.
The actual task, such as for example updating
the display of information when the actual information
has changed, is delegated to a more specialized object,
to achieve a loose coupling between components.
The difference between a mediator and
chain of responsibility is primarily the complexity
of co-ordinating the tasks.
For example, changing the format of a single image component
from one image type to another image type may be done
simply by using an image converter (mediator),
whereas
exporting the complete document to a particular format
such as HTML may involve delegating control to a
specialized converter that itself needs access to
the original components (chain of responsibility).
We will discuss the Observer pattern in more detail later.
As an example of the Command pattern,
think of how you would realize insertion
and deletion commands in an interactive editor,
with undo!
Turning these commands into an object in which the
information necessary for undoing the command can be stored,
for example having a snapshot of the state stored in
a Memento, it suffices to stack the actual
command objects. To undo a command, pop the stack and invoke
the undo method.
The Strategy pattern may be used
to hide the details of the various layout algorithms
that are available. For example, you may use a straightforward
algorithm that formats the text line by line, or you may
use the much more advanced formatting algorithm of \TeX,
which involves the minimalization of penalties.
These alternatives can be collected in a formatting strategy
hierarchy, that hides the implementation details from the client
by a common interface.
When doing the formatting, you may wish
to separate the traversal of the component tree structure
from the actual formatting operations.
This may be accomplished by employing the Visitor
pattern.
In general it is recommended to abstract
from the data structure and use a more abstract
way, such as an Iterator or Visitor
to access and traverse it.
The State pattern is similar to the dynamic role switching idiom
that has been discussed in section hush-patterns>hush-patterns.
As an example, think of providing viewers for alternative document formats,
such as VRML or PDF, in your application.
Using the State pattern, it suffices to
have a single viewer that changes itself according to the
format of the document viewed.
one-to-many dependencies and notification
In effect, MVC or the Observer pattern can be regarded
as a simple method for constraint propagation.
An advantage is that unexpected updates can be easily dealt
with.
In the implementation of the Observer pattern
there are a number of problems and tradeoffs that must
be considered.
For example, do we allow one observer to
be attached to more than one subject?
Do we allow for alternative update semantics,
for example observer-pull instead of subject-push?
Do we provide facilities for specifying
aspects of interest, so that updates only need
to concern those aspects?
And finally, how do we guarantee mutual consistency
between subjects and observers when we do allow for
alternative update semantics?
(C) Æliens
04/09/2009
Structural patterns
Objects rarely live in isolation.
In slide structural-patterns a selection of the
structural patterns treated in Structural patterns
Pattern Alias Remarks Composite part/whole collections of components Flyweight handle/body extrinsic state, many objects Adaptor wrapper resolve inconsistency between interfaces Bridge handle/body relate abstraction to implementation Decorator handle/body to introduce additional functionality Facade handle/body provides unified interface Proxy handle/body to defer ... remote, virtual, protection Behavioral patterns
Our final category of patterns, behavioral patterns,
concern the construction of algorithms and the assignment
of responsibilities to the objects that cooperate in achieving
some goal.
Behavioral patterns
class
object
Encapsulating behavior
The Observer pattern
Observer
Consequences