by BarryMossman<is_at>primos.com.au
(5th August 2004: article and demostration program
reworked to remove heavy use of Interface declarations as I have
since learnt that these are not recommded in most situations)
This is my second article about the GOF Design patterns. The first
article studied the Creational Patterns, while this one looks at the
Structural Patterns. The first article also gave an overview of where
the patterns came from, and the general discussion of the general
techniques that they promoted. There is a link to my first article at
the bottom of this one, but I will firstly briefly recap a few of the
points from that article.
The source for this article's demonstration program is available
at CodeCentral. See link at the bottom of this document. The program
contains annotated example displays, and also displays some notes
about the patterns, so if you are interested in starting to work with
the patterns it may be a useful utility to have on your desktop
during the learning period.
The GOF design patterns help address the following challenges :
- design ready to accommodate change & growth
- design flexible systems that come ready to handle
reconfiguration and run time tailoring
- code in manner to facilitate reuse during the development and
extension phases ... ie. both external and internal reuse, so that
we are rewarded by efficiencies as the project progresses, coming
for investments made earlier in the project.
- implement change in a way that doesn't overly shorten the
system's useful lifespan
In a multi-person project the design patterns have the additional
utility of providing a shorthand language with which to describe
design options and specifications.
The design patterns were defined in the programming classic
entitled "Design Patterns" by Gamma, Helm, Johnson &
Vlissides. The four authors are commonly described as the Gang Of
Four (GOF) for brevity. The subtitle of the book is "elements of
reusable object-oriented software".
The GOF described various categories of patterns:
- Creational Patterns
- Structural Patterns <===== covered by this article
- Behavioral Patterns
One of the book's key points is that the authors favour using
"object composition" over "class inheritance"
when designing our system's objects. This means that our objects are
assembled at runtime from a number of helper classes working together
to deliver the desired behaviour, rather than being statically
defined at compile time using class inheritance. Objects that are
created in this favoured way offer a great deal of runtime
flexibility, and are better set up for future modification. A
general theme of the design patterns is that they allow the
composition of larger and more flexible structures from smaller
helper classes.
The approach necessitates more physical classes, but is made more
workable where the patterns are used as they help to bring an
understandable structure to the design. The fact that the patterns
are based upon system design structures that have been tested and
refined over time is also of assistance.
Note that the advice is to only to "favour"
object composition over class inheritance, not to stop using
inheritance altogether. The two techniques work well together.
A summary of the patterns
|
Pattern Name |
General Objective |
|
Adapter |
Allows us to provide a new interface for a class that already
exists, allowing reuse of a heritage class where our client
requires a different interface.
Also allows us to build a new class which will have
"pluggable" adapters tailored for individual client
needs. |
|
Bridge |
Allows us to decouple a class from it's interface.
This allows the class and it's interface to be changed
independently over time which can lead to more reuse and less
future shock.
It also allows us to dynamically switch between
implementations at runtime allowing increased levels of runtime
flexibility.
|
|
Composite |
A flexible pattern that allows the client to deal with complex
and flexible tree structures.
The trees can be built from various types of containers or
leaf nodes, and it's depth or composition can be adjusted or
determined at runtime.
The client is simplified as it can deal with the tree as a
single object, as the Composite pattern can take care of dealing
appropriately with all the differing component parts. |
|
Decorator |
Allows us to dynamically modify an object at runtime by
attaching new behaviours, or by modifying existing ones.
Is applied just to specific object instances rather than to
the class as a whole.
Can allow design of "pay as you go" systems where
overhead is incurred only when runtime, or configuration options,
require it.
Is best limited to changing an object's "skin"
rather than it's "guts". |
|
Facade |
This pattern allows us to simplify the client by creating a
simplified interface into a subsystem, or by creating a unified
interface into a group of subsystems.
Potential benefits are to simplify the client,
compartmentalise the client, help future proof our application,
or enable more reuse. |
|
Flyweight |
This pattern optimises memory use when we need a design a
class with which our client will want to create a very large
number runtime of objects.
The pattern is most applicable if there will be clusters of
runtime objects that have similar state (data), as it arranges
sharing of these instances.
The pattern works well with the Composite pattern. |
|
Proxy |
This pattern provides a surrogate object that controls access
to some other object.
The aim is to simplify the client when it needs to use an
object that has complications.
Examples include objects upon a remote system, objects who
have client authentication requirements, or objects that are
expensive to fully create so some client purposes may be served
with just a cut down instantiation. |
Adapter Pattern
This pattern allows us to define a different interface for a class
that already exists. The pattern is also known as a "wrapper".
The class that the client interacts with is called the "adapter"
class, and the class, behind the scenes, that they are actually using
is called the "adaptee" class.
Reasons that we may wish to use the Adapter pattern could be:
There are two implementation approaches for the Adapter pattern:
- CLASS Adapter: our adaptee inherits from the adapter, providing
the new interface
- an advantage is that it will probably be the most efficient of
the two approaches
- OBJECT Adapter: our adaptee is :does not descend from the
adapter, but instead it creates a private instance, and then uses
that instance to service the client's requests
My illustration program demonstrates both Object and Class
Adapters.
Firstly let us look at the client code that is using the Adapter
pattern. The following code shows the client first using the older
Adapatee class, and then using the Adapter with it's new interface.
The heritage object's interface exposes method calls, while the new
look uses properties.
// use the "heritage" object
ShowUserCommentary(1);
ConcreteAdaptee adaptee = new ConcreteAdaptee();
listBox1.AppendText(adaptee.SayWho());
listBox1.AppendText(String.Format("nMade on {0}n", adaptee.SayWhen()));
// use the heritage object with a new interface via an Object Adapter
ShowUserCommentary(2);
ObjectAdapter adapter = new ObjectAdapter();
listBox1.AppendText(adapter.Name);
listBox1.AppendText(String.Format("nMade on a {0} in {1}n",
adapter.DayOfWeek, adapter.Month));
The output is as follows (The "UserCommentary" is in black,
and the "AppendText" output is in blue):

The heritage (Adpatee) class was defined as follows:
// ------------ "heritage" class
public class ConcreteAdaptee {
public string SayWho() {
return this.ToString();
}
public string SayWhen() {
return System.DateTime.Now.ToShortDateString();
}
}
As mentioned above there are two implementation approaches for the
Adapter pattern. The first is the OBJECT adapter where we create a
private instance of the Adaptee inside the adapter, and then
translate from the new interface into the old interface to achieve
the client's wishes. This approach is useful when we are providing an
Adapter to be used with a family of Adaptees as we can choose at
runtime which Adaptee class to instantiate privately. This means that
we have to provide just the one Adapter for use with all Adaptees.
/*----------- Approach #1: OBJECT Adapter
--------------*/
public class ObjectAdapter {
// fields
private ConcreteAdaptee _concreteAdaptee = new ConcreteAdaptee();
// properties
public string Name {
get {
return _concreteAdaptee.SayWho();
}
}
public string DayOfWeek {
get {
DateTime dt = System.DateTime.Parse(_concreteAdaptee.SayWhen());
return (dt.DayOfWeek.ToString());
}
}
public string Month {
get {
DateTime dt = System.DateTime.Parse(_concreteAdaptee.SayWhen());
return CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[dt.Month-1];
}
}
}
The other Adapter pattern implementation is a Class Adapter where we
inherit the Adapter from the Adaptee's class. This is more efficient
as the client will work directly with an object, rather than the
Adapter needing to create it's hidden private object and doing double
handling translation behind the scenes.
/*----------- Approach #2: CLASS Adapter
--------------*/
public class ClassAdapter: ConcreteAdaptee{
// properties
public string Name {
get {
return base.SayWho();
}
}
public string DayOfWeek {
get {
DateTime dt = System.DateTime.Parse(base.SayWhen());
return (dt.DayOfWeek.ToString());
}
}
public string Month {
get {
DateTime dt = System.DateTime.Parse(base.SayWhen());
return CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[dt.Month-1];
}
}
}
Bridge Pattern
This pattern allows us to decouple a class from it's interface.
The pattern is also known as a "handle". The class that
provides the interface is called the Abstraction, and the class that
provides the service is called the Implementor. The client creates
both, and then advises the Abstraction that it is to use this
specific Implementor for this run.
A simple abstract class with subclassed implementations already
give us similar functionality, but the implementations are
permanently bound to the abstraction. The Bridge pattern allows to
make changes to either the interface or the implementation
independently of each other. This flexibility may become useful in
the future as it helps to future proof our systems against unexpected
change requirements. It will aid reuse and extension if we can vary
each independently in this way. The pattern also allows us to
dynamically switch implementations at runtime giving the possibility
increased runtime flexibility.
Deja vu ?
Doesn't this sound a bit like the Adapter pattern ?
Although the Bridge pattern is similar to the Adapter
pattern, they are different in intent and timing. The Adapter
pattern intent is to allow us to use an implementation via a
different interface. This is normally done after the
implementation has been published and is in use. The Bridge pattern
intent is to allows us to use multiple implementations with
possibly multiple interfaces. This is normally part of the original
design of the implementation itself.
My illustration program uses the Abstraction to call an Implementor
that states it's name and tells the time. It then switches to another
Implementor and makes the same call again. The new Implementor states
it's own name, and tells the time in a different format. Here are the
client calls:
ShowUserCommentary(1);
ImplementorBase implementor = new ConcreteImplementorA();
ConcreteAbstraction abstraction = new ConcreteAbstraction();
abstraction.Implementor = implementor;
listBox1.AppendText(abstraction.SayWho());
listBox1.AppendText(String.Format("n{0}", abstraction.SayWhen()));
// now access use the same calls & interface to access a different
// Implementor
ShowUserCommentary(2);
implementor = new ConcreteImplementorB();
abstraction.Implementor = implementor;
listBox1.AppendText(abstraction.SayWho());
listBox1.AppendText(String.Format("n{0}",
abstraction.SayWhen()));
Here is the output that we get:

Firstly let us look at the implementation of the Abstraction.
// --- Concrete Abstraction
// The interface allowing access to the Implementor.
public class ConcreteAbstraction {
// fields
ImplementorBase _Implementor;
// properties
public ImplementorBase Implementor {
set {
_Implementor = value;
}
}
// methods
public string SayWho() {
if (_Implementor == null)
throw new Exception("You must assign an Implementor
before using the Abstraction.");
return _Implementor.GetName();
}
public string SayWhen() {
if (_Implementor == null)
throw new Exception("You must assign an Implementor
before using the Abstraction.");
return _Implementor.GetTime();
}
}
And finally the Implementors.
// --- Concrete Implementations
// No public memebers. The client should only access methods via an
// Abstraction instance.
abstract public class ImplementorBase {
// methods
internal string GetName() {
return this.ToString();
}
internal abstract string GetTime() ;
}
public class ConcreteImplementorA: ImplementorBase {
// methods
override internal string GetTime() {
return System.DateTime.Now.ToString();
}
}
// A different implementation of the same services
public class ConcreteImplementorB: ImplementorBase {
// fields
private readonly DateTime _CSharpBLaunch = new System.DateTime(2003,5,6);
// methods
override internal string GetTime() {
return String.Format("{0} days since C#B launch",
System.DateTime.Now.Subtract(_CSharpBLaunch).Days.ToString());
}
}
Composite Pattern
This pattern allows us our client to work with complex and dynamic
tree structure objects.
The tree is built from two families of object. One family are
containers (Composites), and the other family are terminal nodes
(Leaves). Any Composite, at any level in the tree, can contain Leaves
or further Composites, so the tree structure can be of any depth. The
tree's structure can be determined, or altered, at run time making
this a very powerful and flexible pattern.
A focus of the pattern is to simplify the client by allowing it
operate, with generic code, upon the whole tree, a branch from the
tree, or just a single leaf. The use of this pattern will simplify
the client as it is working with tree objects generically regardless
of whether the object is a composite which in turn contains objects,
an empty composite, or just a terminal leaf node. We avoid a dense
set of switch blocks from having to be littered throughout our
client.
The pattern will also future proof the client somewhat as it will
not be impacted if we add further types of composite or leaves to
build the tree from. It is working with these objects generically and
did not know which concrete classes it was dealing with anyway.
The pattern's above objective relies upon the fact that we can
design a common interface for both Composites & Leaves. There are
two conflicting design considerations:
the danger is that if the common interface, for example,
contains members that are only appropriate for Composites, then we
.run the danger of client code making an inappropriate call against
a Leaf object.
We can handle this inside the Leaf by having a null
implementation, but this may just hide a client bug. We want to
employ strong typing to avoid such bugs in the first place. If, for
example, there is a separate Composite interface, and the
Composite-only members are defined down the inheritance chain away
from the Leaves we will have better safety. The cost of course is
that our client has become more complex as it needs to test which
form of object it is dealing with.
The answer is to put as much functionality as possible into their
common ancestor, providing separate implementations via member
overrides. It helps if we consider a Leaf to be just a permanently
empty Composite. For the remaining members where safety is
required we move to Plan B. My demonstration program illustrates
these issues.
There is a further illustration of the composite pattern within
the Flyweight pattern's demonstration as
these patterns can work well together.
This first illustration of the composite pattern has a tree
structure which is built from two types of composite, and two types
of Leaf. Either composite type can contain either leaf type.
Firstly our client builds a multi-level tree, and then asks the
tree to document itself via the SayWho method. This method is
supported at both the composite or leaf levels. The tree as a whole
is just another Composite and therefor accepts the SayWho method
also.
The SayWho behaviour at each level is to print it's class name,
and to indicate semi-graphically it's depth within the tree. When the
SayWho method is called against a Composite, it in turn calls SayWho
against each object which it contains. This behaviour recurses
through the whole tree which demonstrates the powerful utility of the
pattern. Here is the client code:
// Create a "tree" structure
ComponentBase tree = new ConcreteContainer1();
tree.Add(new ConcreteLeaf1());
ComponentBase container = new ConcreteContainer2();
ComponentBase container2 = new ConcreteContainer2();
container2.Add(new ConcreteLeaf2());
container2.Add( new ConcreteLeaf1());
container.Add(container2);
container.Add( new ConcreteLeaf1());
tree.Add(container);
ComponentBase leaf = new ConcreteLeaf1();
tree.Add(leaf);
// The SayWho method processes the tree as a whole. It returns a
// string that portrays the structure semi-graphically.
ShowUserCommentary(1);
listBox1.AppendText(tree.SayWho());
This produces the following output:

The client then steps through the lower level of the tree to
reinforce the idea that the method can work with either Composites or
Leaves. Again the call against a Composite causes the whole structure
to be documented:
// Now step through the 1st level of the tree. The same
method is
// working with both Composites or Leaves.
ShowUserCommentary(2);
foreach (ComponentBase obj in tree) {
listBox1.SelectionColor = System.Drawing.Color.MediumBlue;
listBox1.AppendText(obj.SayWho());
listBox1.AppendText("------------n");
}
This produces output as follows:

The client then demonstrates further capabilities of the Composite
pattern. It firstly jumps to a specific tree position rather than
navigating forward a node at a time. It then performs a method which
requires the tree to process itself in a reverse direction.
/* Position to a specific position within the structure;
the 1st
child of the root's 2nd child. ie. we will be 3 deep in the
structure. This demonstrates the use of an indexer into the tree */
ComponentBase node = tree[1][0];
listBox1.AppendText(node.SayWho());
listBox1.SelectionColor = System.Drawing.Color.MediumBlue;
/* the following call demonstrates a call that works backwards
through the tree */
listBox1.AppendText(String.Format("The above object is {0} deep in the tree"
,(node.GetDepth()).ToString()));

Finally the client demonstrates how to handle any essential
differences between the composite & leaf node's interfaces.
/* Demonstrate how to handle any essential differences in
composite
& leaf interfaces. It makes no sense to try and delete an object
from with a Leaf node. If the node object is a Composite delete
it's child object. Remember that we are positioned within the tree */
ShowUserCommentary(4);
if (node is ContainerBase) {
ComponentBase objToDelete = node[0];
if (objToDelete != null) {
listBox1.AppendText(System.String.Format("Deleting
{0}n",objToDelete.ToString()));
((ContainerBase)node).Remove(objToDelete);
listBox1.SelectionColor = System.Drawing.Color.MediumBlue;
listBox1.AppendText(node.SayWho());
}
}

Enough talk ? Firstly we build an Abstract ancestor class for both
Composite and Leaf classes. This will contain logic and fields common
to both. This "graphical" illustration of the depth of the
object within the tree is maintained in the _indicateNesting field.
The IncreaseIndent method is called to increment the object's depth
whenever it is added into a container. This behaviour recurses
whenever a container is added inside an outer container. The GetDepth
method illustrates backwards navigation through the tree using an
object's reference to it's parent.
// --- Abstract Class
abstract public class ComponentBase {
// fields
private string _indicateNesting = "==";
private ComponentBase _parent = null;
// properties
abstract public ComponentBase this[int index] {get;}
internal ComponentBase Parent {
get {return _parent;}
set {_parent = value;}
}
internal string Indentation {
get {return _indicateNesting;}
set {_indicateNesting = value;}
}
// methods
// Add an object into this container (if this is a container)
abstract public void Add(ComponentBase aComponent);
// Increment the graphical indication this object's depth within the
tree
virtual internal void IncreaseIndent(bool Recurse) {
this.Indentation += "==";
}
// Calculate this object's depth within the tree.
public int GetDepth() {
ComponentBase work = this;
int i = 1;
while ((work.Parent != null) & (i < 99)) {
i++;
work = work.Parent;
}
return i;
}
// Provide an enumerator to drive "foreach"
virtual public IEnumerator GetEnumerator() { return null; }
// Build a string that semi-graphical shows this objects structure
// This method is overriden for the container classes
virtual public string SayWho() {
return (System.String.Format("{0}>
{1}n",this.Indentation,this.ToString()));
}
}
Next we have the implementation of the Composite classes.
// --- Container Classes
abstract public class ContainerBase: ComponentBase {
// Fields
private ArrayList ChildContents = new ArrayList();
// Properties
override public ComponentBase this[int index] {
get {
if (index >= ChildContents.Count)
throw new ArgumentException("No such
child");
return (ComponentBase)ChildContents[index];
}
}
// Methods
override public void Add(ComponentBase aComponent) {
ComponentBase newChild = (ComponentBase)aComponent;
newChild.Parent = this;
newChild.IncreaseIndent(false);
ChildContents.Add(aComponent);
}
override public IEnumerator GetEnumerator() {
return ChildContents.GetEnumerator();
}
override internal void IncreaseIndent(bool Recurse) {
foreach (ComponentBase xx in ChildContents) {
// if this is another container handle all it's children
too
if (xx is ContainerBase) {
((ContainerBase)xx).IncreaseIndent(true);
}
xx.Indentation += "==";
}
// only handle our own indentation once
if (!Recurse)
this.Indentation += "==";
}
// Removes an object into this Container.
public void Remove(ComponentBase aComponent) {
ChildContents.Remove(aComponent);
}
override public string SayWho() {
string st = "";
foreach (ComponentBase xx in ChildContents) {
st += xx.SayWho();
}
return (base.SayWho() + st);
}
}
public class ConcreteContainer1: ContainerBase {
}
public class ConcreteContainer2: ContainerBase {
}
Finally we have the implementation of the Leaf classes. There is very
little to implement at this level as the Component class has the more
complex behaviour, and what little there is required for the Leaves
has mostly been done in the Abstract ancestor class.
// --- Leaf Classes
abstract public class AbstractLeaf: ComponentBase {
// properties
override public ComponentBase this[int index] {
get { return null; }
}
// methods
override public void Add(ComponentBase aComponent) {
throw new ApplicationException("Cannot ADD to LEAF
nodes.");
}
}
public class ConcreteLeaf1: AbstractLeaf {
}
public class ConcreteLeaf2: AbstractLeaf {
}
I guess this looks like a lot of work, but we need to balance this by
the fact that this is a very powerful and flexible pattern that will
significantly simplify the client where it needs to process flexible
and dynamic structures such as these trees
Decorator Pattern
This useful pattern allows us to dynamically modify an object at
run time by attaching new behaviours, or by modify existing ones. The
class to which we are going to add the new behaviour is called the
Component, and the new behaviours are added by using various
Decorators to operate upon the Component. The Decorator is a new
class that is added into the system. The Component class does not
need to, and will not, be aware of it's existence.
The Decorator's interfaces are compatible with the Component so we
can use either to address the Component.
The pattern is applicable when designing new systems, and is also
a useful option during a system modification project.
We could, of course, achieve the objective of attaching new
behaviours to our Component class by inheriting sub-classes from the
Component at compile time. The Decorator pattern has a number of
benefits to static inheritance:
- The new behaviours can be selectively applied at run time,
rather than statically at compile time. This allows us to design
flexible systems that are configurable by set up options or user
selections.
- The new behaviours can be selectively applied to just specific
instances rather across the whole class to all instances.
- The pattern allows us to both add and withdraw
behaviours. If a behaviour is added by a Decorator we can remove the
behaviour by just detaching the Decorator.
- The pattern allows us to design systems that operate on a "pay
as you go" basis where overhead is only incurred when and if
the Decorator is employed.
- In a system maintenance situation we may be able to implement
change with less risk by using the Decorator pattern. We are able to
extend or change existing behaviours, or to add new behaviours,
without the Programmer necessarily having access to the Component
class.
In a situation where there are many different Component
classes, all with the same interface, we would be forced to create
an equal number of sub-classes if we were to use static inheritance
to implement the new behaviours. The Decorator pattern may enable us
to use just one Decorator to work with all of the component classes.
Before proceeding we should make clear what the Decorator pattern
is not. The GOF make a distinction between "changing
the skin" of an object versus "changing it's guts".
The Decorator pattern is only making changes to the Component from
the outside. If more invasive changes are required it would be better
to look to the Strategy pattern where the Component would outsource
some of it's functionality to one of several Strategy classes.
The pattern bears a relationship to the Adapter pattern:
My illustration program has a Component class which has the
familiar SayWho method. The demonstration then adds various
Decorators to modify the SayWho behaviour. It then changes the
sequence which the Decorators are applied to achieve a different
effect. Finally it shows how a Decorator can add new behaviour to the
Component class.
The Component and Decorator clases are unlikely to share a common
base class, however we need to be sure that the Decorators implement
the same interface as the Component. We would also like to write
generic code that can deal with both Components and Decorators. For
this reason I have defined an interface called IGOFComponent that
both the Component and Decorator classes implement. Since there is no
common base class we need to use the Interface name, rather than a
class name, in our client's variable declarations.
There is a second interface named IDecorator that is inherits from
IGOFComponent and enables us to extend the Component's capabilities
if required as is demonstrated in my program.
The client is coded as follows:
// show the native SayWho behaviour before decoration
ShowUserCommentary(1);
IGOFComponent component = new ConcreteComponent();
listBox1.AppendText(component.SayWho());
// now apply 1st form of decoration; convert to uppercase
ShowUserCommentary(2);
IGOFComponent decorator = new ConcreteDecorator1(component);
listBox1.AppendText(decorator.SayWho());
// now apply 2nd form of decoration on top; make a sentance
ShowUserCommentary(3);
IGOFComponent decorator2 = new ConcreteDecorator2(decorator);
listBox1.AppendText(decorator2.SayWho());
// now apply the decorator in the reverse sequence to show a
// different result; everything will be in upper case.
ShowUserCommentary(4);
decorator = new ConcreteDecorator2(component);
decorator2 = new ConcreteDecorator1(decorator);
listBox1.AppendText(decorator2.SayWho());
// now use a capability that has been added by decoration
ShowUserCommentary(5);
decorator = new ConcreteDecorator2(component);
listBox1.AppendText(((IDecorator)decorator2).SayWhen());
The output is:

The interfaces are defined as follows. Note that I have called the
first interface IGOFComponent rather than the GOF's name of
IComponent to avoid confusion with the .Net component of the same
name. The Idecorator interface illustrates functionality that is
introduced by the use of the Decorator.
// --- Interfaces
public interface IGOFComponent {
// methods
string SayWho();
}
public interface IDecorator: IGOFComponent {
// methods
string SayWhen();
}
We then implement the Component interface:
// --- Concrete Component
public class ConcreteComponent: IGOFComponent {
// methods
public string SayWho() {
return this.ToString();
}
}
We then create a abstract ancestor upon which to base the various
Decorators. It is here that we implement the new SayWhen behaviour
which is added to the Component object by the Decorators.
>// --- Abstract Decorator
abstract public class AbstractDecorator: IDecorator {
// fields
protected IGOFComponent _concreteComponent;
// constructor
public AbstractDecorator(IGOFComponent aComponent) {
_concreteComponent = aComponent;
}
// methods
public string SayWhen() {
return String.Format("When = {0:f}",DateTime.Now);
}
abstract public string SayWho();
}
Finally we implement the Decorators.
// --- Concrete Decorators
public class ConcreteDecorator1: AbstractDecorator {
// constructor
public ConcreteDecorator1(IGOFComponent aComponent): base(aComponent) {
}
//methods
override public string SayWho() {
return _concreteComponent.SayWho().ToUpper();
}
}
public class ConcreteDecorator2: AbstractDecorator {
// constructor
public ConcreteDecorator2(IGOFComponent aComponent): base(aComponent) {
}
// methods
override public string SayWho() {
char [] delimiter = new char[] {'.'};
string beforeDecoration = _concreteComponent.SayWho();
string [] split = null;
split = beforeDecoration.Split(delimiter);
return System.String.Format(
"I am from namespace {0} and my class name is {1}.",split);
}
}
Facade Pattern
This pattern allows us to assist the client by creating a
simplified interface into a subsystem, or by creating a unified
interface into a group of subsystems. This can be desirable in both
an initial system design, and in a system maintenance scenario.
In this pattern we design a Facade class that presents a simple
interface that is suitable for our client's needs, and then we
outsource into this Facade class any plumbing tasks required to
obtain the services offered via the interface. This could include the
selection of the actual classes that form the subsystem, their
instantiation and configuration, building of parameters, calling
methods, etc. The client has a simple view of the world that is
consistent with it's needs, and any complexity that is associated
with dealing with the servicing subsystem is isolated into one point,
and away from application logic.
The subsystems that are being used are not aware of the fact that
they are being called via a facade.
In an initial system design situation our motivation may be to
create a system that is logically broken down into several
subsystems. This will have a number of advantages:
The GOF promote a application design that favours "object
composition" over "class inheritance". I described the
differences between these two approach in my earlier article that
described the GOF's Creational
Patterns. In summary this type of design dynamically assembles
object behaviour via the interaction a number of smaller helper
classes, rather than solely using static object inheritance to
assemble our object's behaviours at compile time. The downside to
this design option is that our application will contain more physical
classes than a system that is built just using class inheritance. The
use of the Facade pattern can reduce this as a issue as our client
can still deal with what looks like relatively simple objects.
In a system maintenance scenario the use of the Facade pattern may
allow us to extend the useful life of a subsystem whose interface has
become dated or out of step with the current requirements. Maybe
there are lots of options that are no longer applicable, or are still
applicable but just not to our client.
The application will often need just a single instance of the
Facade, so it is often used in conjunction with the Singleton pattern
that was described in the above article.
My illustration program uses needs to obtain a greeting message
from a group of inconsistent subsystems. It uses a facade to simplify
itself so that it can obtain the greeting with a simple call.
// The facade pattern builds us what seems a simple
greeting message
ShowUserCommentary(1);
ConcreteFacade facade = new ConcreteFacade();
listBox1.AppendText(facade.Greeting);
Here is the output:

The first code snippet is just part of my demonstration example,
and is not part of the Facade pattern, but my illustration doesn't
make much sense unless I show it here. This is the simulation of the
subsystems that the facade is going to simplify from the client's
perspective.
/* Some silly classes to simulate a complex subsystem whose
interface that
we want to simplify with a facade.
1/ A class that provides us with a variable greeting message format.
2/ A class that can provide the datetime in caller specified format
3/ A class that can tell us our name in either upper or lower case.
We are wanting our client to be able to get a simple timed, named greeting
without getting into lots of details that are not relevant to this client's
use of the sub-system. */
// --- Enumerations
public enum GreetingStyles {Terse, Chatty};
// --- Sub-Systems Classes
public class SubSys_GreetingText {
// methods
public string GetText(GreetingStyles style) {
switch(style){
case GreetingStyles.Chatty:
return "Hello and welcome, my name is {0} and the time is {1}";
case GreetingStyles.Terse:
return "{0}: {1}";
default:
throw new ApplicationException("Invalid style requested.");
}
}
}
public class SubSys_Time {
// methods
public string GetTime(string format) {
string work = String.Format("{{0:{0}}}",format);
return String.Format(work,DateTime.Now);
}
}
public class SubSys_Who {
// methods
public string GetName(Object obj, bool aUpper) {
return aUpper?obj.ToString().ToUpper():obj.ToString();
}
}
Now back to the Facade itself. It needs to work with the above
subsystems to obtain the greeting message for the client. All of the
formatting options are an overkill for this client, so the facade has
made this into a simple property access.
// --- Concrete Facade
public class ConcreteFacade {
// fields
private SubSys_GreetingText _greetingText;
private SubSys_Time _greetingTime;
private SubSys_Who _greetingName;
// properties
public string Greeting {
get {
/* The facade object is where we have the detailed knowledge of
how
to use the subsystems that we are proving a facade for.
Here we
assemble an outwardly simple greeting from a few classes
with
interfaces that are too complex for our simple
requirement. */
string _greeting = _greetingText.GetText(GreetingStyles.Chatty);
string _time = _greetingTime.GetTime("f");
string _name = _greetingName.GetName(this,true);
return (String.Format(_greeting,_name,_time));
}
}
// constructors
public ConcreteFacade() {
// initialise the various subsystems that we will be
using
_greetingText = new SubSys_GreetingText();
_greetingTime = new SubSys_Time();
_greetingName = new SubSys_Who();
}
}
Flyweight Pattern
The Flyweight pattern is designed for situations where we would
like to use objects in our system design, but are concerned about
doing so because a very large quantity of these objects will be
required at runtime. The Flyweight pattern allows us to economically
use objects in this case by automatically sharing an existing
instance, rather than creating a new one, whenever the client asks to
create an object where a mostly similar one is already in existence.
This allows us to design a system where we achieve the benefits of an
object orientated design even where it would seem that the memory
cost of all the individual objects would too expensive.
Where object instances are being shared we are also obviously
sharing the instance's data fields (termed "state" by the
GOF). Flyweight objects have two classes of data; intrinsic data and
extrinsic data. The shared data that is held within the flyweight
instance's fields is the "intrinsic" data. Any data that is
unique to each separate use of the instance is called "extrinsic"
data, and has to be held outside of the instance somehow.
The flyweight pattern is only really applicable if most of the
object's data can be made intrinsic (shared). The pattern allows the
most memory saving where there is either a large quantity of
intrinsic data associated with each instance, or where the actual
data at runtime allows a lot of sharing to occur. The memory savings
come at a cost of extra computational resources required to locate
the correct instance and to pass extrinsic data back and forth.
Flyweights are not applicable if our application needs to use code
such as "if (flyweightA == flyweightB)". The problem is
that flyweightA and flyweightB may share the same instance behind the
scenes, although the client regards them as separate objects.
The client uses a Flyweight Factory to create flyweight instances,
and is not aware that reuse is occurring. It thinks that is always
been given a fresh new instance, although of course it is having to
somehow store the extrinsic data and then pass it into the flyweight
whenever it is needed. This means that objects are a little more
clumsy than normal objects, but at least the client is able to focus
upon business issues without being bogged down with the plumbing
involved in arranging the sharing.
There are "shared" and "unshared" flyweights.
The "shared" versions are as described above. The
"unshared" ones are just normal single use, single instance
classes, which implement the same interface as their "shared"
relations. The same Flyweight factory can build both as this will
simplify life for the client. It will also help to future-proof the
client as we will be able to easily change the class of the
flyweights in a future version of the application by just changing
the Flyweight Factory. The client will be able to operate unchanged
with the new Flyweight objects as long as the new flyweights
implement the old interface (see my article about the GOF Creational
patterns in the links below).
The Flyweight pattern can be used within the Composite pattern
allowing us to cheaply create a large number of Leaf nodes. The leaf
nodes would be shared flyweights, and the containers would be
unshared. There is a restriction however as the fact that the
intrinsic data must be shared means that we will not be able to keep
a reference pointing to it's container in each leaf node. This will
restrict the navigation through the tree in an upwards direction
unless we can hold the parent reference within extrinsic data.
My illustration program for the Flyweight pattern is within a
Composite pattern context. I build a tree where the root is a
document. It can contain sentences which are themselves containers.
The sentences contain words and punctuation, which are the leaf nodes
and are implemented as shared flyweights. The illustration seeks to
show the use of both shared & unshared flyweights, also intrinsic
& extrinsic data.
The tree is built from some sentences extracted from a Borland
press release. Each word or piece of punctuation, is created as a
shared flyweight object and is added into it's particular sentance
container. The leaf object is then asked whether it seems to close
the sentence. If so the sentence container is added into the
document, and a new sentence container is created as an unshared
flyweight object. The "intelligence" as to whether the leaf
seems to close the sentence is outsourced to the leaf object, and is
intended to demonstrate the kind of benefit that we are achieving
from the leaf being an object. The client is fairly simple and clear
due in part to the benefits coming from the Flyweight pattern and OO.
// Create Flyweight factory, and then unshared flyweight
containers
// for the whole document and the 1st sentence.
FlyweightFactory factory = new FlyweightFactory();
IGOFComponent document = factory.CreateDocument();
IGOFComponent sentence = factory.CreateSentence();
IGOFComponent word;
ShowUserCommentary(1);
// Load the document's text from disk, and then break it up into
// a collection of individual words & punctuation.
MatchCollection itemList = LoadAndBreakUpUnformatedDocument();
// Process each item in the collection. Create a Flyweight object
// for the item, and add it into it's sentence container. Create new
// sentances as required. The flyweight objects have a property which
// indicates whether this object closes the current sentance. This OO
// working for us as this simplifies the client.
foreach (Match m in itemList) {
if (m.Length > 0) {
word = factory.CreateWord(m.ToString());
sentence.Add(word);
if (word.IsASentenceCloser) {
document.Add(sentence);
sentence = factory.CreateSentence();
}
}
}
Let us ignore the LoadAndBreakUpUnformatedDocument() call1 for the
moment as it is not related to the Flyweight pattern.
We are creating and using shared flyweight objects here, but the
client is not aware of this optimisation. It remains simple thanks to
the flyweight pattern.
The tree has been built from unformatted data. Once it has been
built this demonstration then instructs the flyweight instance that
contains the word "Borland" that it is to be coloured red
if it is to be written. This is achieved via intrinsic data stored in
the specific single instance that contains the word "Borland".
It affects all uses of the word "Borland" within the tree
as they all refer to the same shared instance.
The tree is then instructed to Write itself. The Composite pattern
works with the Flyweight containers & leaf nodes to print the
tree's data. The Write behaviour of the flyweight leaf node is to
underline the word if it appears within a glossary list known to the
flyweight class. This again demonstrates intrinsic data and the type
of client benefit to be obtained by the words being objects. The leaf
node's Write behaviour also causes the 1st word of each sentence to
be bolded. This demonstrates the use of extrinsic data. Each
individual use of a word shares the same single flyweight instance.
The word's text is the same and is shared, but each use may have it's
own individual position within it's own sentence. The sentence
position is stored externally to the flyweight, and is passed
extrinsic data at Write time with the above formatting behaviours.
Here is the client code that formats the word Borland, and then
causes the document to print itself. Again the client has been made
simple by OO.
// cause the word "Borland" to be written with a red font;
to
// demonstrate the the incidents are shared flyweights, and to show
// use of intrinsic data.
word = factory.CreateWord("Borland");
word.colour = System.Drawing.Color.Red;
// Cause the document to write. The leaf node object's Write
// behaviour demonstrates the benefits being obtained by the fact
// that the words are objects, and illustrates the use of intrinsic
// & extrinsic state.
document.Write(listBox1,1);
Now lets us look at the output achieved. Remember that the input to
this was plain unformatted text.

Now remember that my illustration of the Flyweight is within the
context of a Composite pattern, so we need a interface for the nodes
within the Composite pattern:
// --- Interfaces
public interface IGOFComponent {
// properties
Color colour {set;} // font colour: only meaningful for leaves
bool IsOnlyPunctuation {get;} // is this a "word" or is it only
// punctuation; only meaningful for
// leaves
bool IsASentenceCloser {get;} // does this leaf indicate the end of
the
// the end of the sentence; only
// meaningful for leaves
//methods
void Add(IGOFComponent aComponent); // only meaningful for
// containers
void Write(System.Windows.Forms.RichTextBox richtextbox,
int aPosition); // meaningful for either leaves or containers,
// but 2nd paramater only meaningful leaves
// (it is extrinsic state
showing the position
// of the word within the sentence).
}
Next we have the FlyWeight factory. This is where the sharing occurs.
The factory should only create a new instance where the object, that
the client has called, for has unique intrinsic data.:
// --- Flyweight factory
/* The client uses this factory to create both the "shared" & "unshared"
flyweight objects. The unshared ones could be created outside the factory,
but that would make life more complex for the client.
The method called CreateWord creates "shared" flyweights (words), and the
other Createxxx methods create "unshared" flyweights (sentences and the
whole document). */
public class FlyweightFactory {
// fields
private Hashtable Flyweights = new Hashtable();
// methods
public IGOFComponent CreateWord(string aWord) {
IGOFComponent testWord = (IGOFComponent)Flyweights[aWord];
if (testWord == null) {
testWord = new FlyLeaf(aWord);
Flyweights.Add(aWord, testWord);
}
return testWord;
}
public IGOFComponent CreateSentence() {
return new FlySentence();
}
public IGOFComponent CreateDocument() {
return new FlyDocument();
}
}
I did not create an abstract shared ancestor for the Composite and
leaf nodes, as the demonstration required no generic behaviour, and
it just distracted from what I am trying to illustrate here. I have
connected the two classes by having them both implement the
IGOFComponent interface. So now lets us look at the implementation of
the Container nodes. These are unshared Flyweights, which are really
just normal classes which happen to implement the same interface as a
shared Flyweight.
We can see an example of extrinsic data here. Any reuse of a an
individual word will share a Flyweight instance. They share the
word's text value, as well as the font colour that will be used to
print the word. What they don't share is the position within the
sentence for each individual use of that word. If a Flyweight
operation needs such extrinsic data it needs to be passed in as a
parameter. In the demonstration program the shared Flyweight's Write
method needs the word's position within the sentance as it wants to
bold the first word in each sentence. The extrinsic data for each
context needs to be stored external to the Flyweight somehow. In this
example it is inferred from the position of the reference to the
shared Flyweight in it's context, ie. within the Composite's
container node.
// --- Flyweight UNSHARED class: container nodes in our Composite
pattern
abstract public class AbstractUnsharedFlyContainer: IGOFComponent {
// fields
private ArrayList _children = new ArrayList();
// properties
public Color colour {
set {
throw new ApplicationException(
"Colour not relevant for sentences.");
}
}
public bool IsOnlyPunctuation {
get{ return false;} // default value; overriden for
leaves
}
public bool IsASentenceCloser {
get{return true;} // default value; overriden for
leaves
}
// methods
public void Add(IGOFComponent aComponent) {
_children.Add(aComponent);
}
public void Write(System.Windows.Forms.RichTextBox richtextbox,
int aPosition) {
int i = 1;
/* the position of the word in the sentance is an example of
a flyweight's extrinsic data. It is passed into the flyweight
whenever it is needed. In this case it is needed so that the 1st
word in each sentance can be bolded. */
foreach (IGOFComponent leaf in _children) {
leaf.Write(richtextbox, i);
if (!leaf.IsOnlyPunctuation)
i ++;
}
}
}
public class FlySentence: AbstractUnsharedFlyContainer {
}
public class FlyDocument: AbstractUnsharedFlyContainer {
}
Now let us look at the shared Flyweights; the words and punctuation
items within a sentence. The main things to notice is the intrinsic
data which is stored in the class's fields, and the use of both
intrinsic and extrinsic data within the Write method.
// --- Flyweight SHARED class: leaf nodes in our Composite
pattern
public class FlyLeaf: IGOFComponent {
// fields; --- can only be "intrinsic" data (see BDN article)
private string _word;
private Color _colour = Color.Blue; // default
// properties
public Color colour {
set { _colour = value;}
}
public bool IsOnlyPunctuation {
get{
//return Regex.IsMatch(@"W*",_word); // C#B bug ? Does not
work
return Regex.IsMatch(
@"[!#$*()-:;,.""?]",_word);
}
}
public bool IsASentenceCloser {
get{
/* The sentance has been broken down into words & "punctuation".
Each punctuation item is in it's own flyweight item, except for
quoted "sentance closers" being either a quoted period or
exclamation mark. These come as a pair, eg either ." or !" */
switch (_word) {
case ".": return true;
case @".""": return true;
case "!": return true;
case @"!""": return true;
default: return false;
}
}
}
// constructors
public FlyLeaf(string aWord) {
_word = aWord;
}
// methods
public void Add(IGOFComponent aComponent) {
throw new ApplicationException("Cannot ADD to LEAF nodes.");
}
/* Some fairly silly formatting so that we can see some "benefit"
coming from our object. */
public void Write(System.Windows.Forms.RichTextBox richtextbox,
int aPosition) {
// save existing font colour & style
System.Drawing.Color saveColour = richtextbox.SelectionColor;
System.Drawing.Font saveFont = richtextbox.SelectionFont;
System.Drawing.FontStyle saveFontStyle
= richtextbox.SelectionFont.Style;
// override colour to that specified for this word (intrinsic
// state)
if (saveColour != _colour) richtextbox.SelectionColor = _colour;
// use extrinsic state; set word bold if it is the 1st word in
// it's sentence
System.Drawing.FontStyle newFontStyle =
(aPosition ==1)
? System.Drawing.FontStyle.Bold:
System.Drawing.FontStyle.Regular;
// underline any word found in the "glossary" (instrinsic
// state again)
if (IsWordInGlossary(_word)) newFontStyle
|= System.Drawing.FontStyle.Underline;
// override the listbox's font's style with the above changes
richtextbox.SelectionFont = new Font(saveFont,newFontStyle);
// write the word to the list box
richtextbox.AppendText(String.Format("{0} ", _word));
// restore the listbox's font & colour attributes
richtextbox.SelectionFont = saveFont;
richtextbox.SelectionColor = saveColour;
}
/* Simulate a glossary function */
private bool IsWordInGlossary(string aWord) {
switch (aWord) {
case "Kahn":
return true;
case "Fuller":
return true;
default:
return false;
}
}
}
Finally you might like to see the LoadAndBreakUpUnformatedDocument
method from the client where I loaded the Press Release text and then
roughly broke it appart into it's constituent words and punctuation
items. This is nothing to do with the Flyweight design pattern, but I
had a bit of fun with the .Net Regex class to do this, and you may be
interested. The regex facility is very powerful. You can experiment
with it using the excellent free ware tool called Expresso from
Ultrapico (see link at the end of this document). Regex has a Matches
function which matches a supplied string against a regular expression
pattern. It puts all matches into a collection object. My pattern
causes the text to be roughly broken up into words, numbers,
"sentence closers", and individual punctuation items.
I have one confession to make; I had to edit the press release a
little to make this work. I had to deprive Mr Fuller of his middle
initial as it's following fullstop caused my function to prematurely
flag the termination of the sentence.
/* Obtain some data for the demonstration to work with. A section
of a
Borland press release is loaded from a file, and then is broken up into
a collection of words, numbers and punctuation. */
private MatchCollection LoadAndBreakUpUnformatedDocument() {
/* collection will contain:
* sentance closers; fullstop, exclamation mark (quoted or unquoted)
.+""+|!+""
* misc punctuation
[!#$*()-:;,.""?]
* numbers
d+
* words
w* */
Regex regex = new Regex(@".+""+|!+""+|[!#$*()-:;,.""?]|d+|w*",
RegexOptions.IgnoreCase
| RegexOptions.Multiline
| RegexOptions.IgnorePatternWhitespace
| RegexOptions.Compiled
);
RichTextBox rich = new RichTextBox();
const string fileName = "Flyweight words.rtf";
try {
rich.LoadFile(fileName);
}
catch (System.IO.FileNotFoundException e) {
throw new ApplicationException(String.Format
("File "{0}" is needed by this
demonstration; {1}",
fileName, e.Message));
}
return regex.Matches(rich.Text);
}
Proxy Pattern
The Proxy pattern's role is to provide the client with a
surrogate, or gatekeeper, object that controls access to some other
object. The GOF named the object that the client deals as the Proxy
object, and the object that it gives us access to is called the
RealSubject.
The client thinks that the Proxy is the real object, and is
unaware that it is using this other, behind the scenes, object. This
is achieved by the fact that the Proxy implements the RealSubject's
interface.
There are various situations where we obtain advantage from using
a Proxy:
There is some similarity to the Decorator pattern as both patterns
implement the interface of some other object, and stand between it
and the client. The difference is in intent. The Proxy does not allow
us to add or subtract capabilities from the behind the scenes object
as the Decorator does. It's intent is to provide a gatekeeper when it
is inconvienet or undesirable to access the RealSubject.
My illustration program shows a Remote Proxy. The client needs to
use a remote server, and has been simplified by use of the Proxy.
Here is the client call using what looks just to be a normal class.
// Use a method on a remote server. The Proxy pattern simpifies
the
// client so that it can focus upon the business issues of what the
// object does for us, rather than confusing the issue by all the
// surrounding remoting plumbing.
RemProxy proxy = new RemProxy();
listBox1.AppendText(proxy.SayWho());
We need to start the "Remote Server" before pressing the
"Use Proxy" button otherwise you will get the following
error message followed by an exception.

The "remote server" is part of the demonstration program
that is available at CodeCentral. The RemoteInterface.dll is the
interface that is shared between the client's ProxyTest class and the
Remote Server which is the exe called remoteServer.

Once we run the Remote Server we will see the following

Now when we press the client's "Use Proxy" button we can
see the desired result. We can see that the Remote Server has been
accessed by the audit trail within the DOS box window, and we can see
that the result of the SayWho call has been returned to the client
for display.

The interface has been declared in it's own project so that it can
be shared by the Remote server, the client, and the dll that the
client uses for the demonstration.
namespace RemoteInterface
{
public interface IRemoteInterface {
string SayWho();
}
}
Here is the Proxy Class. The main things to note are that the
reference to the RealSubject is in the field called _server. The
proxy class aranges for the remote connection, handles exceptions,
and makes the request for the client.
public class RemProxy : IRemoteInterface {
// Fields
private IRemoteInterface _server;
// Methods
public string SayWho() {
TcpChannel channel = new TcpChannel();
string classAndServerName = "";
try {
ChannelServices.RegisterChannel(channel);
if( _server == null )
_server = (IremoteInterface)Activator.GetObject
(typeof(IRemoteInterface),
"tcp://localhost:8085/MyRemoteClassKnown");
try {
classAndServerName = _server.SayWho();
}
catch (System.Net.Sockets.SocketException) {
MessageBox.Show("You must start the supplied "remote"
server before pressing the Proxy button. The server also runs on this computer.",
"Problem",MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
throw;
}
}
finally {
ChannelServices.UnregisterChannel(channel);
}
return String.Format("My name is {0}.",classAndServerName);
}
}
For the sake of completeness here is the implementation of the
RealSubject with the Remote server.
class Server {
[STAThread]
static void Main(string[] args) {
TcpChannel channel = new TcpChannel(8085);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(MyRemoteClassKnown), "MyRemoteClassKnown",
WellKnownObjectMode.Singleton);
System.Console.WriteLine("Press <enter> to exit.");
System.Console.ReadLine();
}
public class MyRemoteClassKnown: MarshalByRefObject, IRemoteInterface {
public string SayWho() {
System.Console.WriteLine("SayWho method has been called.");
return this.ToString();
}
}
}
Conclusion
This article has examined the Structural Patterns from those
described by the GOF in their book titled "Design patterns".
I think that the study of their design patterns is a worthwhile thing
to do. I found the following links helpful while studying the
patterns myself and while preparing this article. The book itself is
a good investment as it provides supplementary detail upon the
problems that the patterns are trying to solve, the elements of the
solution, and the consequences and trade-offs involved in using the
patterns.
Look out for my next article which will look at the Behavioural
patterns.
Links