0% found this document useful (0 votes)
2 views21 pages

06 TheCodeProject

Uploaded by

Sumit Sandal
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views21 pages

06 TheCodeProject

Uploaded by

Sumit Sandal
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

[Link]

print=true

All Topics, C#, .NET >> C# Programming >> Design and Architecture C#
[Link] Windows, .NET
Win32, VS
Dev
Illustrated GOF Design Patterns in Posted 6 Nov 2002

C# Part II: Structural I Updated 7 Nov 2002


159,339 views
By ian mariano

Part II of a series of articles illustrating GOF Design Patterns in C#

29 votes for this article.


Popularity: 6.84. Rating: 4.68 out of 5.

Download source files - 3 Kb


Please notice that this pdf file contains extracts from a couple of different web
Abstract pages from "[Link]". Only the text regarding Adapter, Facade,
Proxy and Command are required reading.

Design Patterns, Elements of Reusable Object-Oriented Software by Erich Gamma, Richard


Helm, Ralph Johnson, and John Vlissides [also known as the Gang of Four (GOF)] has been a de
facto reference for any Object-Oriented software developer. This article is Part II of a series of
articles illustrating the GOF Design Patterns in C#. We will discuss the Adapter, Bridge,
Composite, and Decorator patterns. Part III of this series will cap off the rest of the Structural
patterns not discussed in this article. It is assumed the reader is familiar with basic C# syntax
and conventions, and not necessarily details of the .NET Framework.

Background

In Design Patterns, each pattern is described with its name (and other well-known names); the
motivation behind the pattern; its applicability; the structure of the pattern; class/object
participants; participant collaborations; pattern consequences; implementation; sample code;
known uses; and related patterns. This article will only give a brief overview of the pattern, and
an illustration of the pattern in C#.

A design pattern is not code, per se, but a "plan of attack" for solving a common software
development problem. The GOF had distilled the design patterns in their book into three main
subject areas: Creational, Structural, and Behavioral. This article deals with the Structural
design patterns, or how objects are composed.

This article is meant to illustrate the design patterns as a supplement to their material. It is
recommended that you are familiar with the various terms and object diagram methods used to
describe the design patterns as used by the GOF. If you're not familiar with the diagrams, they
should be somewhat self-explanatory once viewed. The most important terms to get your head
around are abstract and concrete. The former is a description and not an implementation,
while the latter is the actual implementation. In C#, this means an abstract class is an interface,
and the concrete class implements that interface.

Structural Patterns

To quote the GOF, "Structural patterns are concerned with how classes and objects are
composed to form larger structures. Structural class patterns use inheritance to compose

1/11
[Link]

interfaces or implementations. As a simple example, consider how multiple inheritance mixes


two or more classes into one. The result is a class that combines the properties of its parent
classes. This pattern is particularly useful for making independently developed class libraries
work together."

Adapter

The Adapter structural design pattern is used to "Convert the interface of a class into another
interface clients expect. Adapter lets classes work together that couldn't otherwise because of
incompatible interfaces." (GOF) It's also known as a "Wrapper." There are two basic types of
Adapters: class and object. The structure of a Class Adapter uses multiple inheritance to adapt
one interface to another:

C# only supports single inheritance of classes, but it does allow multiple inheritance of
interfaces. This inheritance is always public, unlike C++, where you can inherit from classes and
interfaces using differing access modifiers. In contrast, an Object Adapter relies on object
composition:

As an illustration ([Link] in the sample code) of a Class adapter, suppose we have an ICar
interface:

public interface ICar


{
void Drive();
}

We create a concrete implementation in a class, CToyota. In a later project, we have a concrete


CCessna class that needs to be adapted to be drivable:

2/11
[Link]

public class CCessna


{
public void Fly()
{
[Link]("Static runup OK, " +
"we're off in our C172...");
}
}

To create a class Adapter for this, we would create a new class, CDrivableCessna, and inherit
from both CCessna and ICar:

public class CDrivableCessna : CCessna, ICar


{
public void Drive() { [Link](); }
}

Using inheritance, we've made it possible to adapt a concrete CCessna to be used by clients the
same way they'd use an ICar:

ICar oCar = new CToyota();


[Link]("Class Adapter:\nDriving an Automobile...");
[Link]();

oCar = new CDrivableCessna();


[Link]("Driving a Cessna...");

[Link]();

As one can see, multiple inheritance [MI] is quite useful, but can lead to its own set of problems
if not executed properly. The other solution is to create an object Adapter. Instead of using MI to
make a drivable Cessna, we create a concrete CDrivableCessna2 which only inherits from ICar,
and contains an instance of CCessna (the adaptee):

public class CDrivableCessna2 : ICar


{
private CCessna m_oContained;

public CDrivableCessna2()
{
m_oContained = new CCessna();
}

public void Drive() { m_oContained.Fly(); }


}

The semantics for driving are exactly the same for the client (refer to the sample code,)
however, I find that creating an Object Adapter is cleaner way to use the Adapter pattern
because you are only exposing the expected interface to the client.

You'd use the Adapter pattern when (GOF):

z you want to use an existing class, and its interface does not match the one you need.
z you want to create a reusable class that cooperates with unrelated or unforeseen classes,
that is, classes that don't necessarily have compatible interfaces.

3/11
[Link]

z (object adapter only) you need to use several existing subclasses, but it's impractical to
adapt their interface by subclassing every one. An object adapter can adapt the interface
of its parent class.

C# is quite useful for the Adapter Pattern. In fact, the example code shows creation of a
pluggable adapter; that is, we use interface adoption, eliminating the assumption that other
classes see the same interface. "Put another way, interface adaptation lets us incorporate our
class into existing systems that might expect different interfaces to the class." (GOF) As you can
see in the example code, we could swap out the class Adapter with the object Adapter and get
the same results. C# was built for this!

Bridge

A Bridge pattern allows one to "Decouple an abstraction from its implementation so that the two
can vary independently." (GOF) A prime example of this is the deferring of windowing operations
in ATL (C++.) The Bridge pattern structure:

An abstraction can be defined, which uses an underlying reference to an implementor. It may bit
difficult to grasp at first, but the following example ([Link]) should help.

The act of flying airplanes differs from one type of airplane to the next. The underlying principles
are the same to fly a single engine vs. a multiengine airplane, but the operations required to
perform the flight may not be. A Bridge pattern allows us to implement flying an airplane for
both single engine and multiengine aircraft.

We create an interface for the implementation of flying an airplane:

public interface IFlyImpl


{
void Fly();
}

We can then create different concrete classes that implement the interface:

public class CSingleEngineFly : IFlyImpl


{
public void Fly()

4/11
[Link]

{
[Link]("SEL: Mixture rich, throttle " +
"smoothly to full...we're off!");
}
}

public class CMultiEngineFly : IFlyImpl


{
public void Fly()
{
[Link]("MEL: Mixture rich, props high " +
"RPM, throttles smoothly to full...we're off!");
}
}

Our abstraction, CAirplane, will contain a reference to an object which implements IFlyImpl.
This way, we can use either concrete implementation:

public class CAirplane


{
private IFlyImpl m_oFlyImpl;

public IFlyImpl FlyImplementation


{
get { return m_oFlyImpl; }
set { m_oFlyImpl = value; }
}

public CAirplane()
{
m_oFlyImpl = null;
}

public void FlyTheAirplane()


{
if(null == m_oFlyImpl)
throw new Exception(
"FlyImplementation is not set!");

m_oFlyImpl.Fly();
}
}

The client can then choose the implementation to use:

CAirplane o = new CAirplane();

[Link] = new CSingleEngineFly();


[Link]();

[Link] = new CMultiEngineFly();


[Link]();

A Bridge pattern makes it very easy to create extensible software. You are not bound to one
particular implementation of something that's abstracted, as in the case of the airplane in the
example above. Switching implementations "on the fly" becomes trivial.

Composite

5/11
[Link]

There is often a problem in software design where you need to create a hierarchy of objects and
also need to treat each element of the hierarchy uniformly. The Composite structural design
pattern accomplishes this be defining primitive and composite objects. Primitives can be
composed into more complex systems, which can in turn be composed, and so on. The structure
of the Composite pattern looks like this:

You would use the Composite pattern when (GOF):

z you want to represent part-whole hierarchies of objects.


z you want clients to be able to ignore the difference between compositions of objects and
individual objects. Clients will treat all objects in the composite structure uniformly.

As an example ([Link]), we're writing software for an airplane manufacturer, and want to
be able to treat items on an equipment list equally. Some equipment is made up of other pieces
of equipment. We begin the Composite pattern by defining a concrete equipment class
CEquipment, and a concrete equipment composite CCompositeEquipment:

public class CEquipment


{
private string m_strName;
private double m_yNetPrice;

public CEquipment(string strName, double yNetPrice)


{
m_strName = strName;
m_yNetPrice = yNetPrice;
}

public string Name { get { return m_strName; } }


virtual public double NetPrice() { return m_yNetPrice; }
virtual public IEnumerator GetEnumerator() { return null; }
}

public class CCompositeEquipment : CEquipment


{
// m_yNetPrice is unused in this class
private ArrayList m_aItems;

public CCompositeEquipment(string strName) : base(strName, 0.0)


{
m_aItems = new ArrayList();
}

6/11
[Link]

public void Add(CEquipment c) { m_aItems.Add(c); }

override public double NetPrice()


{
double yTotal = 0.0;

foreach (CEquipment c in m_aItems)


yTotal += [Link]();

return yTotal;
}

override public IEnumerator GetEnumerator()


{
return m_aItems.GetEnumerator();
}
}

Notice that CCompositeEquipment derives from CEquipment. The GetEnumerator() method can
be used to see if a CEquipment is a composite. The design decision could have been made to
inherit from an IEquipment interface for this example, and it's a choice on what
classes/interfaces implement what functionality whenever you create your Composite pattern in
your design. We could, for example, derive both concrete classes from an IEquipment interface
that supports Name, NetPrice, Add, and GetEnumerator. We would then just stub out Add for a
single CEquipment vs. CCompositeEquipment where we would use the code above. We don't use
interfaces here for simplicity.

Now it is just a matter of creating some derivative equipment classes from our base classes, and
utilizing them in the client:

// I wish these prices were true!


CEquipment oGPS = new CEquipment("Cheap GPS", 125.00);

CEquipment oComm =
new CEquipment("Communications Panel", 50.00);

CEquipment oTCASDisplay =
new CEquipment("TCAS Display", 200.00);

CEquipment oTCASSensors =
new CEquipment("TCAS Sensors", 195.00);

CCompositeEquipment oTCAS =
new CCompositeEquipment("TCAS Stack");

CCompositeEquipment oAvionicsStack =
new CCompositeEquipment("My Cool AVStack");

[Link](oTCASDisplay);
[Link](oTCASSensors);
[Link](oTCAS);
[Link](oGPS);
[Link](oComm);

[Link]("{0} Net Price ${1}", [Link],


[Link]());

IEnumerator i = [Link]();

while([Link]())

7/11
[Link]

{
CEquipment cur = (CEquipment)[Link];

[Link](" {0} - ${1}", [Link], [Link]());


}

The usefulness of the Composite pattern should be quite apparent.

Decorator

Sometimes you need to attach greater responsibility to an object dynamically. This is known as
the Decorator structural design pattern. The GOF tells us to use the Decorator pattern to:

z to add responsibilities to individual objects dynamically and transparently, that is, without
affecting other objects.
z for responsibilities that can be withdrawn.
z when extension by subclassing is impractical. Sometimes a large number of independent
extensions are possible and would produce an explosion of subclasses to support every
combination. Or a class definition may be hidden or otherwise unavailable for subclassing.

The Decorator Structure:

To illustrate using the pattern ([Link]), we'll use the following scenario: Visual Flight Rules
(VFR) is where you fly an airplane by looking out the window. Instrument Flight Rules (IFR) is
where you fly an airplane by referencing instruments, which is required if you fly into clouds, or
where certain visibility restrictions exist. Sometimes you start VFR, but end up flying someplace
where the weather deteriorates and you must then fly IFR (of course you must be rated and
current to do so.)

We can encapsulate dynamically switching from VFR to IFR. We begin with defining VFR flight:

public class CVFRFlight


{
public void Fly()
{

8/11
[Link]

[Link]("Look outside. " +


"Control the aircraft.");
}
}

Suppose we enter bad weather and have to switch to IFR. We're already flying VFR and we need
to continue to do all the things we do VFR, but now with the added twist of IFR. We "decorate"
our VFR flight with IFR rules. Using the Decorator pattern, we come up with the decorator class:

public class CIFRDecorator


{
CVFRFlight m_oVFR; // what we're decorating

public CIFRDecorator(CVFRFlight o)
{
m_oVFR = o;
}

public void Fly()


{
m_oVFR.Fly();
[Link]("Do the scan, cross check, " +
"start again.");
}
}

It's worthwhile to note that we still perform the VFR action, we defer to the action of the
decorated object. So, here it is in action:

CVFRFlight oFlight = new CVFRFlight();

[Link]("VFR, here we go.");


[Link]();
[Link]("Encountering IMC!");

CIFRDecorator oDecorated = new CIFRDecorator(oFlight);


[Link]();

Note that this was a flight example, you certainly can use the Decorator pattern in graphics
programs to add features to objects on the fly, such as to highlight a window or add scroll bars.
Also note that we did not use an abstract Decorator in this example, though it may be wise to do
so. The abstract Decorator would just simply defer to the contained object instance for actions,
whilst the concrete implementation of a decorator would defer then add its functionality:

// CMyDecorator is derived from CDecorator


public void Action()
{
[Link](); // call base class decorator
//(will defer to contained object)
// more stuff
}

Conclusions

Structural design patterns allow for great flexibility in how your software's objects are
composed:

9/11
[Link]

Using the Adapter Pattern allows you to "recast" objects to another interface a client expects.
There are, as with all patterns benefits and trade offs. Some things to be aware of:

z Class adapters commit you to a concrete class. A class adapter will not work if we need to
adapt a class and all its subclasses.
z Object adapters make it harder to override the behavior of the adaptee
z The amount of work in adapting may vary depending on how similar the operations are
z The adapter may not be transparent to all clients

A Bridge pattern allows you to decouple an interface and its implementation; the implementation
is not permanently bound to an interface. This the consequence that you don't have to recompile
the abstraction class nor its clients to use a new implementation. You can also extend the
abstraction and implementors independently.

A Composite pattern has many benefits:

z It makes the client simple. Items in the hierarchy can be treated uniformly.
z It's easy to add new kinds of components into the hierarchy.

Unfortunately the Composite pattern has some drawbacks:

z Overgeneralized design.
z Transparency may supersede safety. Clients may do meaningless things like adding or
removing from a composite node that doesn't support it.

It would be wise to read Design Patterns to familiarize yourself with all the implications of the
Composite pattern.

Using the Decorator pattern gives us more flexibility than just straight inheritance. You can do
things at runtime simply by attaching and detaching them. It simplifies the system. It helps us
to avoid classes that are heavy on features high up in our class hierarchy. Using this pattern also
can mean you cannot rely on the decorator and component being decorated as identical, so you
probably should not rely on object identity when using them. Furthermore, you may get lots of
"little" objects that look all the same, causing some confusion for maintenance or future
development.

Stay tuned for future articles...

Building the Samples

Unzip the source files to the folder of your choice. Start a shell ([Link]) and type nmake. You
may have to alter the Makefile to point to the correct folder where your .NET Framework libraries
exist.

History

2002-11-06 Initial Revision

References

z Design Patterns, Elements of Reusable Object-Oriented Software. Erich Gamma, Richard


Helm, Ralph Johnson, and John Vlissides. Addison Wesley Longman, Inc. 1988. ISBN 0-
201-63498-8.

10/11
[Link]

All Topics, C#, .NET >> C# Programming >> Design and Architecture C#
[Link] Windows, .NET
Win32, VS
Dev
Illustrated GOF Design Patterns in Posted 11 Nov 2002

C# Part III: Structural II Updated 12 Nov 2002


45,163 views
By ian mariano

Part III of a series of articles illustrating GOF Design Patterns in C#

15 votes for this article.


Popularity: 5.1. Rating: 4.33 out of 5.

Download source files - 3 Kb

Abstract

Design Patterns, Elements of Reusable Object-Oriented Software by Erich Gamma, Richard


Helm, Ralph Johnson, and John Vlissides [also known as the Gang of Four (GOF)] has been a de
facto reference for any Object-Oriented software developer. This article is Part III of a series of
articles illustrating the GOF Design Patterns in C#. We will discuss the Facade, Flyweight, and
Proxy patterns. It is assumed the reader is familiar with basic C# syntax and conventions, and
not necessarily details of the .NET Framework.

Background

In Design Patterns, each pattern is described with its name (and other well-known names); the
motivation behind the pattern; its applicability; the structure of the pattern; class/object
participants; participant collaborations; pattern consequences; implementation; sample code;
known uses; and related patterns. This article will only give a brief overview of the pattern, and
an illustration of the pattern in C#.

A design pattern is not code, per se, but a "plan of attack" for solving a common software
development problem. The GOF had distilled the design patterns in their book into three main
subject areas: Creational, Structural, and Behavioral. This article deals with the Structural
design patterns, or how objects are composed. The first two articles in this series dealt with the
Creational patterns and the first half of the Structural patterns. This article finishes off the
Structural patterns as described by the Gang of Four.

This article is meant to illustrate the design patterns as a supplement to their material. It is
recommended that you are familiar with the various terms and object diagram methods used to
describe the design patterns as used by the GOF. If you're not familiar with the diagrams, they
should be somewhat self-explanatory once viewed. The most important terms to get your head
around are abstract and concrete. The former is a description and not an implementation,
while the latter is the actual implementation. In C#, this means an abstract class is an interface,
and the concrete class implements that interface.

Structural Patterns

To quote the GOF, "Structural patterns are concerned with how classes and objects are

1/9
[Link]

composed to form larger structures. Structural class patterns use inheritance to compose
interfaces or implementations. As a simple example, consider how multiple inheritance mixes
two or more classes into one. The result is a class that combines the properties of its parent
classes. This pattern is particularly useful for making independently developed class libraries
work together."

Facade

Often in software development, there are time where a complex system exists, and there is a
need to simplify its use. As software architects, we've often had to provide a contextually
meaningful "interface" to existing systems in such a way as to simplify their use. The facade
pattern solves our problem:

In C#, as it is in many object-oriented languages, this is one of the easiest patterns to use (refer
to the sample code [Link].) Suppose we have an aircraft, composed of various subsystems:
The engine and its controls, the avionics, and the flight control surfaces. Flying the aircraft
entails knowledge and use of the various subsystems, and after a while, experience melds these
together. Flying an airplane becomes second nature, working the various subsystems together to
achieve a flight. Our subsystems are encapsulated in several classes, with a CFly class providing
a facade to flying:

public class CFly


{
private CEngine m_oEngine;
private CAvionics m_oRadios;
private CControls m_oControls;

public CFly()
{
m_oEngine = new CEngine();
m_oRadios = new CAvionics();
m_oControls = new CControls();
}

public void Takeoff()


{
// use encapsulated subsystems to takeoff
}
}

A Facade certainly means less work for the client, while still allowing direct use of the
subsystems.

Flyweight

2/9
[Link]

[Link]([Link]),
"airframe final assembly"));

// perform the run


[Link]("Running aircraft assembly...");

foreach (RunNode r in aRun)


[Link]([Link]);

This illustration is very simplified. ArrayLists are fun and easy, but as seen in the illustration,
there's the problem of state reuse and management. In a real-world implementation, the
mapping of state to the flyweight would probably be done using a binary tree or some other
efficient storage mechanism, with a pool, perhaps, of state.

Proxy

The GOF define a Proxy as a pattern to "Provide a surrogate or placeholder for another object to
control access to it." Sometimes, objects are expensive to create and initialize. It can be a good
design decision to defer the expensive operations until a time when they are actually needed, to
use a lightweight placeholder in lieu of the expensive object. You see this in Microsoft Word®
where an object has been inserted into a document, but doesn't need to be fully loaded until
edited or rendered.

There are variants of proxies: remote, where you represent a remote object through a local
object; virtual, which provides on demand creation of expensive objects; protection, which
controls access to the original object; and a smart reference, also known as a smart pointer,
which provides "decorated" functionality to the proxied object (such as a smart pointer,
persisted object loader, or wrapper object for multithreaded operations to a single-threaded
object.)

The Proxy structural design pattern's structure looks like this:

For our example ([Link]) we'll use the following scenario: An airport Fixed Base of Operations
[FBO] manager needs software that will help him manage hundreds of airplanes. His database of
aircraft only contains basic aircraft information; however, he has partnered with other operators
at his airport and others to use several web services and databases for more details about each
aircraft such as fees, incidentals, and maintenance. Using a Proxy, we gain an advantage by
using basic aircraft information, and only loading the details from these varied sources when
actually needed [just in time.]

6/9
[Link]

In our illustration we highly simplify things and won't actually query databases or web services
for brevity, but it should illustrate the basic idea. We begin by defining the classes for the full
aircraft details, and its proxy:

public class AircraftDetails


{
public string MaintenanceRecords
{
get { return "--> List of maintenance records."; }
}

// ...
}

public class AircraftDetailsProxy


{
// ...

public AircraftDetailsProxy(string strName,


string strTailNo, string strOwner)
{
m_oReal = null;

// ...
}

public AircraftDetails Details


{
get
{
if (m_oReal != null) return m_oReal;

// and load data


m_oReal = new AircraftDetails();

return m_oReal;
}
}
}

Notice that the Details method actually performs the expensive operation of creating and
initializing the details. In a real world implementation, it would go out and fetch information at
that point. Furthermore, the AircraftDetails class itself may use proxies for on-demand
information, rather than loading everything at once.

Conclusions

Structural design patterns allow for great flexibility in how your software's objects are
composed:

A Facade allows you to shield clients from the dirty work of directly using subsystems. It also
allows you to eliminate complex or circular dependencies, allowing independent development of
subsystems and clients, and it still allows for direct use of subsystems as necessary.

The Flyweight pattern is useful where a limited set of objects are used a large number of times
performing stateful operations. One must consider the states that can be externalized for the
operations. The Flyweight pattern will not help if there are as many external (extrinsic) states as
there are objects that need to be shared. One must also be aware of the data storage costs
involved. "Ideally, extrinsic state can be computed from a separate object structure, one with far
smaller storage requirements." (GOF) The sample code was a poor example of real-world

7/9
[Link]

efficient storage of extrinsic state, even though it illustrated the Flyweight pattern. The data
structure algorithms studied in computer science courses come in quite handy for this pattern
because efficient data storage and retrieval for the mappings is extremely important in order to
maximize any benefits.

The Proxy pattern allows for additional mechanisms for dealing with objects, such as on demand
creation and initialization of expensive objects. It also allows reference counting (much like
AddRef and Release in old-school COM, where if a reference goes to zero, the object is
removed; or perhaps for a network connection Proxy where if no one is using it, it closes.) A
Proxy can also provide additional housekeeping mechanisms during object access. This pattern
may have the additional side-effect of making it appear that a system is more "snappy" than it
actually is. The use of proxies, caching and other mechanisms can work together to increase the
overall robustness of a system, as well as increase scalability through smart resource usage and
allocation.

Stay tuned for future articles...

Building the Samples

Unzip the source files to the folder of your choice. Start a shell ([Link]) and type nmake. You
may have to alter the Makefile to point to the correct folder where your .NET Framework libraries
exist.

History

2002-11-11 Initial Revision

References

z Design Patterns, Elements of Reusable Object-Oriented Software. Erich Gamma, Richard


Helm, Ralph Johnson, and John Vlissides. Addison Wesley Longman, Inc. 1988. ISBN 0-
201-63498-8.

About ian mariano

This NYC native has been a software developer/consultant for over 14 years and is
currently Chief Software Architect for TransMedia.

Ian is also a musician: classically trained, an electronica dj and currently runs his own
electronica dance label, n space records.

His current piano repetoire currently includes:

Frédéric Chopin Etude Op.10 No.3


Franz Lizt Liebestraum (Notturno No.3)
C.P.E. Bach Solfeggietto
J.S. Bach Invention I, Invention XIII
Beethoven Sonata in Cm Op.13 (Pathetique) Adagio Cantabile and the
Moonlight Sonata.
Jez Confrey Kitten on the Keys
Schumann Träumerei

He also enjoys flying single engine Cessnas, with hopes to begin his Instrument Training
soon, and has yet to take his cat, Random Numbers, aviating.

8/9
[Link]

All Topics, C#, .NET >> C# Programming >> Design and Architecture Beginner
[Link]
C#
Windows, .NET
Illustrated GOF Design Patterns in Win32, VS
Dev
C# Part IV: Behavioral I Posted 13 Nov 2002

By ian mariano Updated 1 Apr 2003


87,736 views
Part IV of a series of articles illustrating GOF Design Patterns in C#

10 votes for this article.


Popularity: 4.32. Rating: 4.32 out of 5.

Download source files - 4 Kb

Abstract

Design Patterns, Elements of Reusable Object-Oriented Software by Erich Gamma, Richard


Helm, Ralph Johnson, and John Vlissides [also known as the Gang of Four (GOF)] has been a de
facto reference for any Object-Oriented software developer. This article is Part IV of a series of
articles illustrating the GOF Design Patterns in C#. We will discuss the Chain of Responsibility,
Command, and Interpreter patterns. The next few articles will conclude the C# illustrations of
the GOF design patterns. It is assumed the reader is familiar with basic C# syntax and
conventions, and not necessarily details of the .NET Framework.

Background

In Design Patterns, each pattern is described with its name (and other well-known names); the
motivation behind the pattern; its applicability; the structure of the pattern; class/object
participants; participant collaborations; pattern consequences; implementation; sample code;
known uses; and related patterns. This article will only give a brief overview of the pattern, and
an illustration of the pattern in C#.

A design pattern is not code, per se, but a "plan of attack" for solving a common software
development problem. The GOF had distilled the design patterns in their book into three main
subject areas: Creational, Structural, and Behavioral. This article deals with the Behavioral
design patterns, or how objects are act together. The first three articles in this series dealt with
the Creational and Structural patterns. This article begins the illustration of the Behavioral
patterns as described by the Gang of Four.

This article is meant to illustrate the design patterns as a supplement to their material. It is
recommended that you are familiar with the various terms and object diagram methods used to
describe the design patterns as used by the GOF. If you're not familiar with the diagrams, they
should be somewhat self-explanatory once viewed. The most important terms to get your head
around are abstract and concrete. The former is a description and not an implementation,
while the latter is the actual implementation. In C#, this means an abstract class is an interface,
and the concrete class implements that interface.

Behavioral Patterns

1/9
[Link]

To quote the GOF, "Behavioral patterns are concerned with algorithms and the assignment of
responsibilities between objects. Behavioral patterns describe not just patterns of objects or
classes but also the patterns of communication between them. These patterns characterize
complex control flow that's difficult to follow at run-time. They shift your focus away from flow of
control to let you concentrate just on the way objects are interconnected."

Chain of Responsibility

There are times when designing software that one comes across the need to pass requests
between objects, and multiple objects at that. The Chain of Responsibility pattern allows more
than one object to handle a request. Request receivers are "chained" until an object handles it.
You move from a specific request handler to the generic, passing the request from object to
object until it is finally handled.

A good example is when you throw an exception from a method. You first get a chance to
handle it in a local try / catch block. If it isn't handled locally, the exception passes to the
caller, and so on up the chain until it is handled. At last, if there are no application exception
handlers, the runtime finally handles it.

The structure of the Chain of Responsibility looks like this:

For our illustration ([Link]), we have the following scenario: We're developing a bug tracking
system for a software company, and depending on the type of bug (UI, functionality, et al.) it
must get handled, routed and so on, but at the least it must be submitted to a bug database. We
begin with defining a BugType structure for enumerating the types of bugs, and a BugHandler
which will be the base class for handling:

public enum BugType { Any, Feature, UI }

public class BugHandler


{
private BugHandler m_oSuccessor; // in order to chain

public BugHandler(BugHandler o) { m_oSuccessor = o; }

virtual public void HandleBug(BugType t)


{
if (m_oSuccessor != null)
{
[Link]("...{0} passing to successor {1}",
[Link]().ToString(), m_oSuccessor.GetType().ToString());

2/9
[Link]

m_oSuccessor.HandleBug(t);
}
else throw new Exception("Bug not handled!");
}
}

Our default handling routine HandleBug just passes along the request, throwing an error if no
successor exists. Our derived classes will call [Link]() if they do not handle the
specific bug type:

public class FeatureBugHandler : BugHandler


{
public FeatureBugHandler(BugHandler o) : base(o)
{
// ...
}

override public void HandleBug(BugType t)


{
if ([Link] == t)
[Link]("--> FeatureBugHandler: {0}", [Link]());
else [Link](t); // pass onto successor
}
}

The client can then "build" a chain of handlers (in any order, mind you). In the sample code, we
create two chains, and fire off HandleBug for each BugType. The output looks like this:

Chain 1 UI:
--> UIBugHandler: UI
Chain 2 UI:
...[Link] passing to successor [Link]
--> UIBugHandler: UI
Chain 1 Feature:
...[Link] passing to successor [Link]
--> FeatureBugHandler: Feature
Chain 2 Feature:
--> FeatureBugHandler: Feature
Chain 1 Any:
...[Link] passing to successor [Link]
...[Link] passing to successor [Link]
--> GenericBugHandler: Any
Chain 2 Any:
...[Link] passing to successor [Link]
...[Link] passing to successor [Link]
--> GenericBugHandler: Any

One could just as easily create and chain together drawing handlers for various UI elements, or
application-specific events. If one wished, you could use a .NET event that "kicks off" the chain.

Command

There are times when developing an application framework that you need to pass requests
between objects without knowing anything about operation requested or the receiver of the
request. By encapsulating the request as an object itself, one can "parameterize clients with
different requests, queue or log requests, and support undoable operations." (GOF) This is the
Command behavioral design pattern. You can separate the requesting object from the object
that "knows" how to fulfill it.

3/9
[Link]

The Command pattern structure:

The GOF recommend using the Command pattern when you want to:

z parameterize objects by an action to perform (much like SqlCommands allowing different


types of command text and execute methods)
z specify, queue, and execute requests at different times. Your Command object may live
independently of a request
z support undo. State can be stored on the Command object, and an "undo" operation
performs a "reverse" of the execute. For unlimited undo/redo, a list of Commands could be
maintained, and one could traverse it backwards or forwards calling "undo" or "execute"
appropriately
z build systems from "primitive or atomic operations" such as transactions

To illustrate using this pattern ([Link],) suppose we are modelling flying an airplane,
specifically, tuning the communication radios. We want to be able to set a frequency, but later
be able to go back to a previous one. We'll define an interface for the radio command:

public interface RadioCommand


{
void Execute(double f);
void Undo();
}

In the future, we may be performing more than just tuning a radio frequency with a radio
command. Our concrete implementation of this command will perform some action on our radio
class, namely setting the desired frequency, or "undoing" the change:

public class ChangeFreqCommand : RadioCommand


{
private double m_fOld; // our old frequency
private Radio m_oRadio; // the radio we're concerned with

public ChangeFreqCommand(Radio o)
{
m_oRadio = o;
m_fOld = 0.0;
}

public void Execute(double f)


{
// store the old frequency, then set to desired

4/9
[Link]

m_fOld = m_oRadio.Frequency;
m_oRadio.Frequency = f;
}

public void Undo()


{
m_oRadio.Frequency = m_fOld;
}
}

Our client will create and use ChangeFreqCommand objects to play with a radio:

ArrayList cmds = new ArrayList();


Radio r = new Radio("Garmin COM", 121.5); // start on guard channel
ChangeFreqCommand c = new ChangeFreqCommand(r);

[Link](125.25); // get ATIS


[Link](c);
c = new ChangeFreqCommand(r);
[Link](121.9); // tune to ground
[Link](c);

// ...

To undo, we just iterate through our ArrayList backwards and call Undo():

[Link]();

foreach(ChangeFreqCommand x in cmds) [Link]();

It's worthwhile to note that we are not checking for bogus Radio or Command states, so the
undo/redo may not always work as planned (see my remarks in the Conclusion of this article.)

Interpreter

I've worked on projects where there was a need to tokenize input, and store it in an application's
"grammar." The Interperter pattern's intent is "Given a language, define a represention for its
grammar along with an interpreter that uses the representation to interpret sentences in the
language." (GOF) This is quite useful if you are assembling commands for batch processing that
need a more "human" way of inputting controlling statements to your batch processes, or just
plain searching a string. You are building or using a syntax "tree," based on the grammar. The
Interpreter structure can be represented as follows:

5/9
[Link]

exercise to the reader.)

Conclusions

Behavioral design patterns allow for great flexibility in how your software behaves:

The Chain of Responsibility frees objects from knowing which other objects handle a request,
objects know the requests will be handled appropriately. The sender and receiver don't need
explicit knowledge of each other. It can greatly expand the flexibility in what responsibilities you
assign to objects. You do, however, have to be aware that there is no guarantee that a request
will be handled, since there is no explicit receiver. It can "fall off the end of the chain..." (GOF)

The Command pattern allows one to):

z Decouple the object that invokes an operation from the one that knows how to perform it.
z Command objects can be extended like any other first-class object
z You can assemble Command objects into a composite to create a "Macro Command"
z New Commands can be created easily without changing existing classes

When using the Command pattern, there are decisions to be made:

z How "deep" or "intellegent" is the command? The [Link] object is


one extreme where it does much of the work by itself. Yours may simply bind a receiver
and actions for the request.
z How do you represent state for undo/redo, and how do you eliminate errors from
accumulating? If you delete a file, how do you "undelete" it? What happens if it is deleted
outside the control of your application?

The Interpreter design pattern helps us to "figure out" a language and represent its statements
in so we can interpret them in code. It works best when your language is simple and when
you're not overly concerned about efficiency. For complex languages, using a parser generator is
a more viable option. Design Patterns has additional insights into the Interpreter pattern and
nice examples in Smalltalk and C++.

Stay tuned for future articles...

Building the Samples

Unzip the source files to the folder of your choice. Start a shell ([Link]) and type nmake. You
may have to alter the Makefile to point to the correct folder where your .NET Framework
libraries exist.

History

2003-04-01 Corrected introduction

2002-11-14 [Link]();

2002-11-13 Initial Revision

References

8/9

You might also like