Monday, 16 July 2012

Design Patterns


 Introduction
When working on a particular problem, it is unusual to tackle it by inventing a new
solution that is completely dissimilar from the existing ones. One often recalls a
similar problem and reuses the essence of its solution to solve the new problem.
This kind of thinking in problem solving is common to many different domains,
such as software engineering.
Design patterns are important building blocks for designing and modelling applications on all platforms. Design patterns help us understand, discuss and reuse
applications on a specific platform. The most commonly stated reasons for studying patterns are; reuse of solutions and establishment of common terminology. By
reusing already established designs, the developer gets a head start on the problem
and avoids common mistakes. The benefit of learning from the experience of others results in that he does not have to reinvent solutions for commonly recurring
problems. The other reason for using patterns is that common terminology brings
a common base of vocabulary and viewpoint of the problem for the developers. It
provides a common point of reference during the analysis and design phase of a
project.
The design patterns are divided into three types: creational, structural, and behavioural. We’ll be looking at two patterns from each category and present these
in a C# point of view. To fully understand design patterns, knowledge of the object oriented paradigm and some familiarity with the Unified Modelling Language
(UML) is required.
Creational Pattern
Creational pattern as the name implies are concerned with the creation of object.
The patterns help you build a part of an application that hides how an object is
created and composed from the representation of the object. The only informationknown of the object is its interface. Creational patterns can be divided in class creational patterns and object creational patterns. The difference lies in that the class
creational patterns use inheritance to instantiate a class, while object creational
patterns delegate the instantiation to another object.
All creational patterns hide which concrete class is used by the system and,
further more they hide how an object is created and put together.
Singleton Pattern
This pattern ensures that there exists only one instance of a class with a global access point to it. There are different situations where it is desired to have a single
instance of a class for example a printer spooler; it would be most unfortunate to
have several printer spoolers. Another example is when you need a single point
of access to a database. C# has the mechanisms to implement the singleton deFigure 4: The structure of the Singleton pattern.
sign pattern. The example illustrates the implementation of a printer spooler. To
instantiate a single instance of the class spooler we use a static variable.
public class Spooler
{
private static Spooler spoolerInstance = null;
private Spooler()
{
}
public static Spooler getSpooler()
{
if(spoolerInstance != null)
return spoolerInstance;
else
{
spoolerInstance = new Spooler();
return spoolerInstance;
}}
}
When the spooler is created the value of the variable instance_flag is changed.
Since the instance_flag is a static class variable there can only be one instance_flag,
thus we have ensured that a single instance of a printer spooler exists. The spooler
is created in the getSpooler method instead of the constructor. Note that the constructor is private, so any attempt to access the Spooler constructor will fail. How
does C# facilitate a global access point for the printer spooler class? By defining a
static class method. Static methods can only be called from the classes and not the
class instances.
For example if we add a static instance, queueThis(string filName), to the
Spooler class.
public class Spooler
{
private static Spooler spoolerInstance = null;
private string [] queueList;
private spooler()
{
}
public static Spooler getSpooler()
{
if(spoolerInstance != null)
return spoolerInstance;
else
{
spoolerInstance = new Spooler();
return spoolerInstance;
}
}
public static Spooler queueThis(string filename)
{
// Code to add filename to the queue
}
}
And we have, by defining the queueThis method, created a global access point to
the printer Spooler. The singleton example was from [2].
Abstract Factory
Another creational pattern is abstract factory. Abstract factory pattern is useful
when you want to create families of related or dependent objects and not revealtheir concrete classes according to [1].
The structural composition of abstract factory patter is shown in the figure 5.
As you can see from the figure you cannot only add and remove objects (AbstractFigure 5: The structure of the Abstract factory pattern.
Product) to an existing factory (ConcreteFactory), you can also add and remove the
factories (ConcreteFactory). Abstract factory pattern reveal only the interfaces of
the products and hide how they are created. This design pattern has a higher level
of abstraction then the Factory method, which is another creational pattern.
With C# you have the means to implement a design made with the abstract
factory pattern, and the best way to show this is by an example.
Imagine you are designing software that builds aeroplanes. First you need to
define the AbstractFactory and the AbstractProducts classes, we call then aeroplaneFactory and aeroplane.
abstract class aeroplane
{
public abstract string type { get; }
}
abstract class aeroplaneFactory
{
public abstract aeroplane getAeroplane();
}
Now we define the concreteFactory for the aeroplaneFactory class and the product
class for the aeroplane class.
class aeroplaneProductMustangP51 : aeroplane
{
string _type = "mustang";public override string type
{
get { return _type; }
}
}
class concreteNorthAmericaFactory : aeroplanFactory
{
public override aeroplane getAeroplane ()
{
return new aeroplaneProductMustangP51();
}
}
Now that we have the factory and the product we are ready to implement the classes
and build our aeroplane. But first we need a client and a main class. For our client
class we implement the testpilot class.
class testpilot
{
public void askformodel(aeroplaneFactory factory)
{
aeroplane aircraft = factory.getAeroplane();
Console.WriteLine("Planemodel {0}",aircraft.type);
}
}
class MainClass
{
static void Main (string[] args)
{
aeroplaneFactory factory = new concreteNorthAmericaFactory();
new testpilot().askformodel(factory);
}
}
Now we are going to add another factory and another type of aeroplane.
class aeroplaneProductFW190 : aeroplane
{
string _type = "Foker-Wulf 190";
public override string type
{
get { return _type; }
}}
class concreteFokerWulfFactory :aeroplanesFactory
{
public override aeroplane getAeroplane ()
{
return new aeroplaneProductFW190();
}
}
We just need to modify the main class a little to be able to use the new factory. Note
that we do not change the client class (testpilot) the interface remains the same.
class MainClass
{
static void Main (string [] args)
{
aeroplaneFactory factory = null;
if (args.length > 0 && args[0] == "P51")
factory = new aeroplaneNorthAmericaFactory();
else if ( args.length > 0 && args[0] == "FW190")
factory = new aeroplaneFokerWulfFactory();
new testpilot().askformodel(factory);
}
}
This simple example shows how you can add a new factory to you system but you
can see it is easy to add new products as well. You just add new aeroplanes and
change in the code how to choose the new products (aeroplanes).
Structural Pattern
Structural patterns suggest ways to put together existing objects into complex structures, in order to achieve new functionality. Class structural patterns use inheritance to compose interfaces and implementation, whereas in object structural patterns an object can reside inside another object. In this chapter we will look more
closely at the patterns Adapter and Composite. In the chapter about Adapter both
class and object approaches of implementing the design pattern will be described.
Adapter
The Adapter pattern sometimes also known as wrapper is used whenever we want
to change the interface of an object into another, desired interface. This is useful
in the following scenario: An application accepts a set of functions or a certaininterface to be implemented. The same application (or class) needs to communicate with an object that provides the functionality we are looking for but does not
support the exact interface required by the application.
Consider for example the following [1]: A graphics application uses an abstract
Shape class. Each graphical shape such as circle, triangle and polygon is a subclass
of Shape and implements it’s own drawing function. The drawing function for a
TextShape object however might be more difficult to implement. Let’s say that we
find an off the shelf object called TextView that provides us with the functionality
we are looking for. TextView however is not compatible with the Shape class.
There are mainly two way of applying the adapter pattern to make the TextView
class work with our application: class and object [1]. Class means that we inherit
Shapes interface and TextViews implementation. Object means that we hold an
instance of TextView inside TextShape and implement Shapes interface in terms of

DisplayText of the TextView class in the following example corresponds to the draw
operation in Shape. Notice how the TextShape class takes an instance of a TextViewobject as an argument in its constructor and later overrides the Draw method of the
Shape class by calling the DisplayText method of TextView and thereby acts as an
adapter for TextView.
class Shape
{
...
public virtual void Draw()
{
}
...
}
class TextView
{
...
public DisplayText()
{
...
}
...
}
class TextShape: Shape
{
private TextView Text;
public TextShape(TextView T)
{
this.Text = T;
}
public override void Draw()
{
this.Text.DisplayText();
}
...
}
An alternative design would be to view the drawing capabilities of each object as
a behaviour that we want all of our graphic objects to display. In other words our
application demands that each shape implements a Draw method (along with any
other methods we might need). Based on our previous discussion on interfaces we
can present an interface, perhaps called IDisplay containing the methods necessary to reflect this particular behaviour. This way the functionality in the TextView
object could be used if we let TextShape inherit from TextView. We can then addthe methods we need to TextShape by letting it implement the IDisplay interface.
This is the class approach of implementing the adapter pattern and would look
something like the following in code:
interface IDisplay
{
void Draw();
}
class TextView
{
...
public DisplayText()
{
...
}
...
}
class TextShape: TextView, IDisplay
{
...
public Draw()
{
this.DisplayText();
}
...
}
Notice that in the class approach, introducing an interface is necessary since C#
does not support multiple inheritance. Which approach is more suitable to use
depends on the situation. In this case if we already have built our application
around a class hierarchy with Shape as an abstract base class, the first approach is
probably more suitable. In other situations it might be a better idea to introduce
an interface. Ultimately it is up to the developer to decide where and when to use
each approach.
 Composite
The composite pattern is designed to deal with situations where a certain object
can either be viewed individually, or as a placeholder for a collection of objects
of the same type. Consider for example a graphics application that will let you
group a collection of simple graphic objects, such as lines and texts, into a picture.
A picture which itself is a graphic object can in turn contain other pictures. The
composite patterns allows us to treat all graphic objects, independent of whetherthey are complex (pictures) or simple (lines), in an uniform fashion. This can be
achieved by introducing an abstract base class that represent both the simple and
complex type. This abstract type contains methods that are shared between the
simple and complex types, and also methods that will let the client access and
perform operations on the complex types children (the objects it contains) [1]. The
diagram in figure 8 illustrates this.
The simplest analogy for describing a composite object is a tree. Each node
object should have the same set of methods such as GetValue, AddChild, RemoveChild and GetChild. Some nodes are of a simple type and cannot have any
children. They are therefore always leaves. In that case we might want to raise an
error upon calling the AddChild method. This can be easily done in C# by creating an exception and throwing it. The GetChild method could return an ArrayList
object (see 3.3.2) as a return value, which will be empty for a leaf object. This can
easily be verified by checking the count property that will be 0 [2].
In the graphics example a picture is a typical node whereas a line or a text
object is a leaf and cannot have any children. This is illustrated in figure 9. Let
us now look at how we can implement a picture and a line class. We will assume
for simplicity that each class contains a draw method, and that the draw method
of the picture class simply calls the draw methods of all of its children. We will
start by defining an abstract graphics class that will contain a draw method, and
the necessary functions for accessing and manipulating children objects.
class graphic
{
public virtual void draw()
{
}
// A list containing the childrenFigure 9: The graphics example illustrated as a tree.
protected ArrayList children;
public bool isLeaf()
{
// Simply check the count property
return children.Count == 0;
}
public virtual void AddChild(graphic)
{
}
public virtual graphic GetChild(int i)
{
}
}
We now derive the picture and the line classes from the graphic class. First the
simple line class:
class line : graphic {
public override void draw()
{
// Implements its own draw function
}
public override void AddChild(graphic g)
{
// This is a simple type object
// Raise an exception
throw new Exception("No children in this class");
}public override graphic GetChild(int i)
{
// Simple type, no children to return
return null;
}
}
And now the complex picture class:
class picture: graphic
{
public override void draw()
{
// Call the draw function for all children
foreach (graphic g in this.children)
g.draw();
}
public override void AddChild(graphic g)
{
this.children.add(g);
}
public override graphic GetChild(int i)
{
return this.children[i];
}
}
Other simple graphic objects such as a text object could be built in the same way
as the line class defined above. It is also worth mentioning that an indexer could
be used instead of implementing the AddChild and GetChild methods.
4.4 Behavioural Pattern
Behavioural patterns are most specifically concerned with communication between
objects. These patterns describe communication between objects in your system
and how the flow is controlled in a complex program. They move the focus away
from the flow of control and let the developer concentrate on the way objects are
interconnected.
Observer
The Observer pattern lets one part of a system know when an event takes place in
another. According to Gamma et. al [1] it is a one-to-many dependency betweenobjects; if one-object changes state the other dependent objects will automatically
be notified and updated.
The most obvious use of the Observer pattern is when a change of one object
requires changing of an unknown number of objects. The notifying object should
not have knowledge about who these objects are. The objects aren’t supposed to
be tightly coupled; the Observer pattern is an example of a decoupling pattern.
It could also be applicable if the abstraction has two aspects and you would like
to encapsulate these aspects in separate objects. This will make the objects more
reusable and allow you to change them independently.
The following class diagram from Gamma et. al [1], figure 10, shows the
relationship between the Subject and the Observer. The Subject may have one
or more Observers, and it provides an interface to attaching and detaching the
observer object at run time. The observer provides an update interface to receive
signals from the subject. The ConcreteSubject stores the subject state interested
by the observers, and it sends notification to its observers. The ConcreteObserver
maintains reference to a ConcreteSubject, and it implements an update operation.
When designing and implementing the Observer pattern in C# we take advantage
of the delegates and events that where introduced in section 3.7. These provide a
powerful way of implementing this pattern without developing specific types. The
delegates permitting anonymous invocation of the bound method and the events
help to expose state changes to interested objects at run time. The delegates and
events are in fact first class members of the Common Language Runtime (CLR);
the foundation of this pattern is incorporated into the core of the .NET Framework.
The Framework Class Library (FCL) makes extensive use of the Observer pattern
throughout its structure.
the subject is the class declaring the event. The subject
class doesn’t have to implement a given interface or to extend a base class. It just
needs to expose an event. The observer must create a specific delegate instance and
register this delegate with the subject’s event. It must use a delegate instance of the
type specified by the event declaration otherwise the registration will fail. Duringthe creation of the delegate instance, the name of the method (instance or static)
is passed by the observer that will be notified by the subject to the delegate. Once
the delegate is bound to the method it may be registered with the subject’s event
as well as it can be unregistered from the event. Subjects provide notification to
observers by invocation of the event.
The following example is from Purdy D. et. al [4] and shows how to use delegates and events in the Observer pattern. The class, Stock, declare a delegate and
an event. The instance variable askPrice fires an event when its value is set.
public class Stock
{
public delegate void AskPriceDelegate(object aPrice);
public event AskPriceDelegate AskPriceChanged;
object askPrice;
public object AskPrice {
set
{
askPrice = value;
AskPriceChanged(askPrice);
}
}
}
The StockDisplay class represents the user interface in the application.
public class StockDisplay
{
public void AskPriceChanged(object aPrice) {
Console.Write("The new ask price is:" + aPrice + "\r\n");
}
}
The main class first creates a new display and a stock instance. Then it creates a
new delegate and binds it to the observer’s AskPriceChanged method. After that,
the delegate is added to the event. Now when we use the set property of the stock
class an event is fired every time. The delegate captures the event and executes
the AskPriceChanged method, which in this case outputs the price in the console
window. Before we quit the application, we remove the delegate from the event.
public class MainClass
{
public static void Main()
{
StockDisplay stockDisplay = new StockDisplay();
Stock stock = new Stock();Stock.AskPriceDelegate aDelegate = new
Stock.AskPriceDelegate(stockDisplay.AskPriceChanged);
stock.AskPriceChanged += aDelegate;
for(int looper = 0; looper < 100; looper++)
stock.AskPrice = looper;
stock.AskPriceChanged -= aDelegate;
}
}
4.4.2 Strategy
The Strategy pattern defines a family of algorithms, encapsulates the related algorithms and makes them interchangeable. This allows the selection of algorithm to
vary independently from clients that use it and allows it to vary over time [4].
An application that requires a specific service or function and that has several
ways of executing that function is a candidate for the Strategy pattern. The choice
of proper algorithms is based upon user selection or computational efficiency. The
client program could tell a driver module (context) which of these strategies to
use and then tell it to carry out the operation. There are a number of cases in
applications where we would like to do the same thing in several different ways
like; compress files using different algorithms or save files in different formats.
The construction behind the Strategy pattern is to encapsulate the number of
strategies in a single module and provide an uncomplicated interface to allow the
clients to choose between these strategies. If you have several different behaviours
that you want an object to perform, it is much simpler to keep track of them if each
behaviour is a separate class, instead of the most common approach of putting
them in one method. This is illustrated in figure 11 from Gamma et. al [1]. By
doing this you can easily add, remove, or change the different behaviours, since
each one is its own class. Each such behaviour or algorithm encapsulated into its
own class is called a Strategy. The strategies do not need to be members of the
same class hierarchy but they do have to implement the same interface [2]. The
new language support for interfaces in C# comes in handy when implementing the
Strategy pattern. C++ programmers typically create interfaces by defining abstract
classes with pure virtual methods. In C#, all interface members are public, and
classes adhering to an interface must implement all methods in the interface.
The following code demonstrates the Strategy pattern, which encapsulates functionality in the form of an object.
interface Strategy
{
void AlgorithmInterface();
}
public class ConcreteStrategyA : Strategy
{
public void AlgorithmInterface()
{
Console.WriteLine(
"Called ConcreteStrategyA.AlgorithmInterface()");
}
}
public class Context
{
private Strategy strategy;
public Context(Strategy strategy)
{
this.strategy = strategy;
}
public void ContextInterface()
{
strategy.AlgorithmInterface();
}
}
The encapsulation of the functionality allows clients to dynamically change algorithmic strategies by specifying the desired strategy.
Context c = new Context(new ConcreteStrategyA());
c.ContextInterface();

No comments:

Post a Comment