Introduction

As a solutions architect, we have to deal with several design patterns in order to design our solution. Design patterns are a way to conceptualize a reusable solution to commonly occurring problem in a given context in software design. Design pattern is today a way to communicate architectural ideas and decisions through a common language. In this series of articles, I will explain the essential design patterns (by the Gang of Four) with real-world code examples. In this first article, I want to talk about creational and structural design patterns.

Talking about the design patterns

In order to explain the essential design patterns, I want to organize the design patterns the same way as the Gang of Four did as creational, structural and behavioral.

Creational design patterns

Factory design pattern: The factory design pattern is used to create instances of classes without specifying the exact class. The essence is: “Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses”. It’s mainly used for the creation of objects regarding to the configuration files or user input.

The UML representation is shown in the Figure 1.

Figure 1

An example in C# is shown in the Listing 1.

public interface ISession

{

void Initiate();

}

public class DatabaseSession : ISession

{

void Initiate()

{ }

}

public class MessageQueueSession : ISession

{

void Initiate()

{ }

}

public class SessionFactory

{

public static ISession GetSession(string session)

{

ISession objResult = null;

switch(session)

{

case “database”:

objResult = new DatabaseSession();

case “mqueue”:

objResult = new MessageQueueSession();

}

return objResult;

}

}

Listing 1

Abstract Factory: It provides a way to encapsulate a group of individual factories that have a common theme. In normal usage, the client software creates a concrete implementation of the abstract factory and then uses the generic interfaces to create the concrete objects that are part of the theme. It’s a factory of factory, so we need to create another layer to the example in the Listing 1.

Flyweight pattern: It’s used to maximize the sharing of objects resulting in reduced memory consumption, for example, you have large amount of small objects that share common information reducing the storage of the objects. It’s an extension of the factory design pattern.

The UML diagram is shown in the Figure 2.

Figure 2

Let’s see an implementation in C# (see Listing 2).

public enum eNumbers

{

One,

Two,

Three,

// .. and so on with every number

}

public class NumbersFactory

{

private Dictionary<eNumbers, Number> _numbers = new Dictionary<eNumbers, Number>();

public Number GetNumber(eNumbers number)

{

if (!_numbers.ContainsKey(number))

{

switch (number)

{

case (eNumbers.One):

{

_numbers.Add(number, new One());

break;

}

case (eNumbers.Two):

{

_numbers.Add(number, new Two());

break;

}

case (eNumbers.Three):

{

_numbers.Add(number, new Three());

break;

}

default:

{

break;

}

}

}

return _numbers[number];

}

}

public abstract class Number

{

protected int _number;

protected string _numberName;

protected int _numberSize;

public abstract void WriteNumber(int numberSize);

}

public class One : Number

{

public One()

{

this._number = 1;

this._numberName = “One”;

}

public override void WriteNumber(int numberSize)

{

this._numberSize = numberSize;

Console.WriteLine(string.Format(“{0} is size {1}”,_numberName, _numberSize));

}

}

public class Two : Number

{

public Two()

{

this._number = 2;

this._numberName = “Two”;

}

public override void WriteNumber(int numberSize)

{

this._numberSize = numberSize;

Console.WriteLine(string.Format(“{0} is size {1}”,_numberName, _numberSize));

}

}

public class Three : Number

{

public Three()

{

this._number = 3;

this._numberName = “Three”;

}

public override void WriteNumber(int numberSize)

{

this._numberSize = numberSize;

Console.WriteLine(string.Format(“{0} is size {1}”, _numberName, _numberSize));

}

}

Listing 2

Singleton design pattern: It’s used to insure that only a single instance of a given object can exist. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects.

The UML diagram is shown in Figure 3.

Figure 3

And the example in C# is shown in the Listing 3.

public sealed class Singleton

{

private static readonly Singleton _instance = new Singleton();

private Singleton() { }

public static Singleton Instance

{

get

{

return _instance;

}

}

}

Listing 3

Builder design pattern: It separates the construction of a complex object from its representation so that the same construction process can create different representations. This pattern is not commonly used. It’s like the abstract factory with the difference that the builder is concerned about how the objects are created and the abstract factory is concerned about what objects are created.

Let’s see the UML diagram for this pattern (see Figure 4).

Figure 4

Let’s see an implementation using C# (see Listing 4).

class Pizza

{

public string Dough { get; set; }

public string Sauce { get; set; }

public string Topping { get; set; }

}

abstract class PizzaBuilder

{

public Pizza pizza { get; protected set; }

public void CreatePizza()

{

pizza = new Pizza();

}

public abstract void BuildDough();

public abstract void BuildSauce();

public abstract void BuildTopping();

}

class HawaiianPizzaBuilder : PizzaBuilder

{

public override void  BuildDough()

{

pizza.Dough = “Cross”;

}

public override void BuildSauce()

{

pizza.Sauce = “Mild”;

}

public override void BuildTopping()

{

pizza.Topping = “Ham+Pineapple”;

}

}

class SpicyPizzaBuilder : PizzaBuilder

{

public override void BuildDough()

{

pizza.Dough = “Pan Baked”;

}

public override void BuildSauce()

{

pizza.Sauce = “Hot”;

}

public override void BuildTopping()

{

pizza.Topping = “Pepperoni+Salami”;

}

}

class Cook

{

public PizzaBuilder PizzaBuilder { get; set; }

public Pizza Pizza { get { return PizzaBuilder.pizza; } }

public void MakePizza()

{

PizzaBuilder.CreatePizza();

PizzaBuilder.BuildDough();

PizzaBuilder.BuildSauce();

PizzaBuilder.BuildTopping();

}

}

static void Main(string[] args)

{

Cook cook = new Cook();

cook.PizzaBuilder = new SpicyPizzaBuilder();

cook.MakePizza();

cook.PizzaBuilder = new HawaiianPizzaBuilder();

cook.MakePizza();

}

Listing 4

Lazy initialization: The idea is to delay the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed (see Listing 5).

using System;

using System.Collections;

using System.Collections.Generic;

public class Fruit

{

private string _typeName;

private static Dictionary<string, Fruit> _typesDictionary = new Dictionary<string, Fruit>();

private Fruit(String typeName)

{

this._typeName = typeName;

}

public static Fruit GetFruitByTypeName(string type)

{

Fruit fruit;

if (!_typesDictionary.ContainsKey(type))

{

// Lazy initialization

fruit = new Fruit(type);

_typesDictionary.Add(type, fruit);

}

else

fruit = _typesDictionary[type];

return fruit;

}

public static void ShowAll()

{

if (_typesDictionary.Count > 0)

{

Console.WriteLine(“Number of instances made = {0}”, _typesDictionary.Count);

foreach (KeyValuePair<string, Fruit> kvp in _typesDictionary)

{

Console.WriteLine(kvp.Key);

}

Console.WriteLine();

}

}

}

class Program

{

static void Main(string[] args)

{

Fruit.GetFruitByTypeName(“Banana”);

Fruit.ShowAll();

Fruit.GetFruitByTypeName(“Apple”);

Fruit.ShowAll();

// returns pre-existing instance from first

// time Fruit with “Banana” was created

Fruit.GetFruitByTypeName(“Banana”);

Fruit.ShowAll();

Console.ReadLine();

}

}

Listing 5

Object pool design pattern: It’s a set of initialized objects that are kept ready to use, rather than allocated and destroyed on demand. A client of the pool will request an object from the pool and perform operations on the returned object. When the client has finished with an object, it returns it to the pool, rather than destroying it. It is a specific type of factory object. It’s mainly used in situations where the cost of initializing a class instance is high, the rate of instantiation of a class is high, and the number of instances in use at any one time is low, such as database connections, socket connections, threads and large graphic objects like fonts or bitmaps.

When writing an object pool, the programmer has to be careful to make sure the state of the objects returned to the pool is reset back to a sensible state for the next use of the object. If this is not observed, the object will often be in some state that was unexpected by the client program and may cause the client program to fail. The pool is responsible for resetting the objects, not the clients.

Structural design patterns

Adapter design pattern: It converts the interface of a class into another interface clients expect. Adapter lets the classes work together that couldn’t otherwise because of incompatible interfaces, by providing its interface to clients while using the original interface.

Let’s see the UML diagram for this pattern (see Listing 5).

Figure 5

The implementation of the design pattern is shown in the Listing 6.

public interface IClient

{

void DoWork();

}

public interface IAdaptor

{

void MethodA();

}

public interface IAdaptee

{

void MethodB();

}

public class Adaptee : IIAdaptee

{

public void MethodB()

{ }

}

public class Adaptor : IAdaptor

{

private Adaptee _objAdaptee;

public Adaptor(Adaptee objAdaptee)

{

this._objAdaptee = objAdaptee;

}

public void MethodA()

{

this._objAdaptee.MethodB();

}

}

public class Client : IClient

{

private IAdaptor _objAdaptor;

public Client(IAdaptor objAdaptor)

{

this._objAdaptor = objAdaptor;

}

public void DoWork()

{

this._objAdaptor.MethodA();

}

}

Listing 6

Bridge design pattern: It decouples an abstraction from its implementation so that the two can vary independently. In other words we make a bridge between the abstraction and its implementation and therefore we won’t have a binding between the two.

Let’s see UML diagram for this design pattern (see Figure 6).

Figure 6

Let’s see an implementation of this design pattern (see Listing 7).

public class Abstraction

{

private Bridge _bridge;

public Abstraction(Bridge bridge)

{

_bridge = bridge;

}

public void Operation()

{

Console.Write(“Using”);

_bridge.OperationImplementation();

}

}

public interface Bridge

{

void OperationImplementation();

}

public class BridgeImplementationA : Bridge

{

public void OperationImplementation()

{

Console.Write(“BridgeImplementationA”);

}

}

public class BridgeImplementationB : Bridge

{

public void OperationImplementation()

{

Console.Write(“BridgeImplementationB”);

}

}

Listing 7

Composite design pattern:  The main idea is to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

The UML diagram for this design pattern is shown in the Figure 7.

Figure 7

Now let’s see the code example in C# (see Listing 8).

using System;

using System.Collections.Generic;

namespace Composite

{

class Program

{

interface IGraphic

{

void Print();

}

class CompositeGraphic : IGraphic

{

private List<IGraphic> child = new List<IGraphic>();

public CompositeGraphic(IEnumerable<IGraphic> collection)

{

child.AddRange(collection);

}

public void Print()

{

foreach(IGraphic g in child)

{

g.Print();

}

}

}

class Ellipse : IGraphic

{

public void Print()

{

Console.WriteLine(“Ellipse”);

}

}

static void Main(string[] args)

{

new CompositeGraphic(new IGraphic[]

{

new CompositeGraphic(new IGraphic[]

{

new Ellipse(),

new Ellipse(),

new Ellipse()

}),

new CompositeGraphic(new IGraphic[]

{

new Ellipse()

})

}).Print();

}

}

}

Listing 8

Decorator design pattern: It allows an objects behavior to be altered at runtime.This change in behavior is accomplished by wrapping an object with a new object.  This new wrapper object is the Decorator. The Decorator object will implement the same interface as the object being wrapped.  Because the decorated object uses the same interface as an undecorated object, other parts of your system do not need to be aware of whether or not one or more decorations are in use. The decorator (wrapper) can now alter the behavior of the object being wrapped by either completely replacing various methods or by altering the behavior of the methods of the object being decorated.

This is very important to implement cross-functional features (aspect-oriented programming) in your applications such as logging, security, transactions, etc. It can be also used to express context-specify aspects to plain objects without changing their implementation (see Listing 9).

public interface IReport

{

void Print();

}

public class Report : IReport

{

public void IReport.Print()

{

HttpContext.Current.Response.Write(“This is the report body.”);

}

}

public class ReportHeaderDecorator : IReport

{

private IReport _innerReport;

public ReportHeaderDecorator(IReport innerReport)

{

_innerReport = innerReport;

}

public void IReport.Print()

{

HttpContext.Current.Response.Write(“<h3>This is the report header</h3>”);

HttpContext.Current.Response.Write(“<hr />”);

_innerReport.Print();

}

}

public class ReportFooterDecorator : IReport

{

private IReport _innerReport;

public ReportFooterDecorator(IReport innerReport)

{

_innerReport = innerReport;

}

public void IReport.Print()

{

_innerReport.Print();

HttpContext.Current.Response.Write(“<hr />”);

HttpContext.Current.Response.Write(“<h6>This is the report footer.</h6>”);

}

}

IReport myReport;

myReport = new Report();

myReport = new ReportHeaderDecorator(myReport);

myReport = new ReportFooterDecorator(myReport);

myReport.Print();

Listing 9

Facade design pattern: It’s mainly used to provide a simpler interface into a more complicated series of complicated interfaces and or sub systems (see Figure 8).

Figure 8

Another UML diagram is shown in the Figure 9.

Figure 9

And an implementation is shown in the Listing 10.

using System;

namespace Facade

{

class Computer

{

class CPU

{

public void Freeze() { }

public void Jump(long addr) { }

public void Execute() { }

}

class Memory

{

public void Load(long position, byte[] data) { }

}

class HardDrive

{

public byte[] Read(long lba, int size) { return null; }

}

CPU cpu = new CPU();

Memory memory = new Memory();

HardDrive hardDrive = new HardDrive();

void StartComputer()

{

cpu.Freeze();

memory.Load(0x22, hardDrive.Read(0x66, 0x99));

cpu.Jump(0x44);

cpu.Execute();

}

static void Main(string[] args)

{

Computer facade = new Computer();

facade.StartComputer();

}

}

}

Listing 10

Proxy design pattern: It provides a Placeholder for another object to control access to it. A proxy, in its most general form, is a class functioning as an interface to something else. The proxy could interface to anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate.

The UML diagram for this design pattern is shown in the Listing 10.

Figure 10

An implementation of this design pattern is shown in the Listing 11.

using System;

namespace Proxy

{

class Program

{

interface IImage

{

void Display();

}

class RealImage : IImage

{

public RealImage(string fileName)

{

FileName = fileName;

LoadFromFile();

}

private void LoadFromFile()

{

Console.WriteLine(“Loading ” + FileName);

}

public String FileName { get; private set; }

public void Display()

{

Console.WriteLine(“Displaying ” + FileName);

}

}

class ProxyImage : IImage

{

public ProxyImage(string fileName)

{

FileName = fileName;

}

public String FileName { get; private set; }

private IImage image;

public void Display()

{

if (image == null)

image = new RealImage(FileName);

image.Display();

}

}

static void Main(string[] args)

{

IImage image = new ProxyImage(“HiRes_Image”);

}

}

}

Listing 11

Conclusion

In this article, I’ve explained the essential design patterns (by the Gang of Four) with UML diagrams and real-world code examples.

Advertisements

2 thoughts on “

  1. Pingback: Design Patterns in Microsoft.NET (Part.1) « MSExpertos

  2. Pingback: MVP Factor

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s