Design patterns in Microsoft.NET. Part 2

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 second article, I want to talk about behavioral design patterns.

Talking about the design patterns

Behavioral design patterns

Chain of Responsibility design pattern: It consists of a source of command objects and a series of processing objects and it’s a way of communicating between objects. Each processing object contains a set of logic that describes the types of command objects that it can handle, and how to pass off those that it cannot to the next processing object in the chain. A mechanism also exists for adding new processing objects to the end of this chain.

You can use this design pattern when you have more than one object that may handle a request, you have a scenario that you need to pass a request to one of several objects without specifying the receiver and you have handlers of a request that should be specified dynamically.

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

01

Figure 1

And an example of this design pattern is found in the Listing 1.

public abstract class Handler

{

public int RequestLimit { get; private set; }

public Handler NextHandler { get; private set; }

 

public abstract void HandleRequest(int request);

 

public Handler(Handler handler, int requestLimit)

{

NextHandler = handler;

RequestLimit = requestLimit;

}

}

 

public class Worker : Handler

{

public Worker(Handler handler)

: base(handler, 10000)

{}

 

public override void HandleRequest(int request)

{

if (request < RequestLimit)

{

Console.WriteLine(“{0} handled a {1} request”, GetType().Name, request);

}

else

{

if (NextHandler != null)

{

NextHandler.HandleRequest(request);

}

}

}

}

 

public class Manager : Handler

{

public Manager(Handler handler)

: base(handler, 20000)

{}

 

public override void HandleRequest(int request)

{

if (request < RequestLimit)

{

Console.WriteLine(“{0} handled a {1} request”,GetType().Name, request);

}

else

{

if (NextHandler != null)

{

NextHandler.HandleRequest(request);

}

}

}

}

 

public class SeniorManager : Handler

{

public SeniorManager(Handler handler)

: base(handler, 50000)

{}

 

public override void HandleRequest(int request)

{

if (request < RequestLimit)

{

Console.WriteLine(“{0} handled a {1} request”,GetType().Name, request);

}

else

{

if (NextHandler != null)

{

NextHandler.HandleRequest(request);

}

}

}

}

 

class Program

{

static void Main(string[] args)

{

SeniorManager seniorManager = new SeniorManager(null);

Manager manager = new Manager(seniorManager);

Worker worker = new Worker(manager);

 

// Run requests along the chain

worker.HandleRequest(5000);

worker.HandleRequest(15000);

worker.HandleRequest(35000);

Console.WriteLine();

manager.HandleRequest(5000);

manager.HandleRequest(15000);

manager.HandleRequest(35000);

Console.WriteLine();

seniorManager.HandleRequest(5000);

seniorManager.HandleRequest(15000);

seniorManager.HandleRequest(35000);

// Wait for user

 

Console.Read();

}

}

Listing 1

Command design pattern: It encapsulates a request as an object, and it’s mainly used to represent and encapsulate all the information needed to call a method at a later time. This information includes the method name, the object that owns the method and values for the method parameters.

Three terms always associated with the command pattern are client, invoker and receiver. The client instantiates the command object and provides the information required to call the method at a later time. The invoker decides when the method should be called. The receiver is an instance of the class that contains the method’s code.

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

02

Figure 2

And the example for this design pattern is shown in the Listing 2.

public interface Command

{

void Execute();

}

 

public class Light

{

public Light() { }

 

public void TurnOn()

{

System.Console.WriteLine(“The light is on”);

}

 

public void TurnOff()

{

System.Console.WriteLine(“The light is off”);

}

}

 

public class FlipUpCommand : Command

{

private Light _objLight;

 

public FlipUpCommand(Light light)

{

this._objLight = light;

}

 

public void Execute()

{

this._objLight.TurnOn();

}

}

 

public class FlipDownCommand : Command

{

private Light _objLight;

 

public FlipDownCommand(Light light)

{

this._objLight = light;

}

 

public void Execute()

{

this._objLight.TurnOff();

}

}

 

public class Switch : Command

{

private Command _objFlipUpCommand;

private Command _objFlipDownCommand;

 

private bool _bIsUp;

public bool IsUp

{

get

{

return this._bIsUp;

}

set

{

this._bIsUp = value;

}

}

 

public Switch()

{

Light objLamp = new Light();

 

this._objFlipUpCommand = new FlipUpCommand(objLamp);

this._objFlipDownCommand = new FlipDownCommand(objLamp);

}

 

public void Execute()

{

if (this._bIsUp)

{

this._objFlipUpCommand.Execute();

}

else

{

this._objFlipDownCommand.Execute();

}

}

}

 

public class PressSwitch {

 

public static void Main(String[] args)

{

Switch objSwitch = new Switch();

objSwitch.Execute();

}

}

Listing 2

Iterator design pattern: It provides a way to sequentially access aggregate objects without exposing the structure of the aggregate.

For example, a tree, linked list, hash table, and an array all need to be iterated with the methods search, sort, and next. Rather than having 12 different methods to manage (one implementation for each of the previous three methods in each structure), using the iterator pattern yields just seven: one for each class using the iterator to obtain the iterator and one for each of the three methods. Therefore, to run the search method on the array, you would call array.search(), which hides the call to array.iterator.search().

The pattern is widely used in C# and in the .NET framework we have the IEnumerator and IEnumerable interfaces to help us to implement iterators for aggregates. When you implement your own aggregate object you should implement these interfaces to expose a way to traverse your aggregate.

You use this when you need a uniform interface to traverse different aggregate structures, you have various ways to traverse an aggregate structure and you don’t want to expose the aggregate object’s internal representation.

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

03

Figure 3

And an example code in C# of this design pattern is shown in the Listing 3.

public class AggregateItem

{

public string Data { get; set; }

public AggregateItem(string data)

{

this.Data = data;

}

}

 

interface Aggregate

{

Iterator GetIterator();

}

 

class AggregateImpl : Aggregate

{

private readonly List<AggregateItem> _aggregate;

public int Count

{

get

{

return _aggregate.Count;

}

}

 

public AggregateItem this[int index]

{

get

{

return _aggregate[index];

}

set

{

_aggregate[index] = value;

}

}

 

public AggregateImpl()

{

_aggregate = new List<AggregateItem>();

}

 

public Iterator GetIterator()

{

return new IteratorImpl(this);

}

}

 

interface Iterator

{

object First();

object Next();

bool IsDone();

object Current();

}

 

class IteratorImpl : Iterator

{

private readonly AggregateImpl _aggregate;

private int _nCurrentIndex;

 

public object First()

{

return _aggregate[0];

}

 

public object Next()

{

object result = null;

if (_nCurrentIndex < _aggregate.Count – 1)

{

result = _aggregate[_nCurrentIndex];

_nCurrentIndex++;

}

return result;

}

 

public bool IsDone()

{

return _nCurrentIndex >= _aggregate.Count;

}

 

public object Current()

{

return _aggregate[_nCurrentIndex];

}

 

public IteratorImpl(AggregateImpl aggregate)

{

_nCurrentIndex = 0;

_aggregate = aggregate;

}

}

Listing 3

Mediator design pattern: – It encapsulates the interaction between a set of objects. The pattern helps to lose couple the object by keeping them from referring each other. You use this design pattern when the behavior is distributed between some objects can be grouped or customized, object reuse is difficult because it communicates with other objects, and objects in the system communicate in well-defined but complex ways.

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

04

Figure 4

And an example of this design pattern is shown in the Listing 4.

public interface Mediator

{

void Send(string message, Colleague colleague);

}

 

public class ConcreteMediator : Mediator

{

public List<ConcreteColleague> Colleagues { get; private set; }

public ConcreteMediator()

{

Colleagues = new List<ConcreteColleague>();

}

 

public void Send(string message, Colleague colleague)

{

foreach (Colleague currentColleague in Colleagues)

{

if (!currentColleague.Equals(colleague))

{

currentColleague.Recieve(message);

}

}

}

}

 

public abstract class Colleague

{

protected Mediator _mediator;

 

public Colleague(Mediator mediator)

{

_mediator = mediator;

}

public abstract void Send(string message);

public abstract void Recieve(string message);

}

 

public class ConcreteColleague : Colleague

{

public int ID { get; set; }

 

public ConcreteColleague(Mediator mediator, int id)

: base(mediator)

{

ID = id;

}

public override void Send(string message)

{

_mediator.Send(message, this);

}

public override void Recieve(string message)

{

Console.WriteLine(“{0} recieved the message: {1}”,ID, message);

}

}

 

class Program

{

static void Main(string[] args)

{

ConcreteMediator mediator = new ConcreteMediator();

ConcreteColleague colleague1 = new ConcreteColleague(mediator, 1);

ConcreteColleague colleague2 = new ConcreteColleague(mediator, 2);

mediator.Colleagues.Add(colleague1);

mediator.Colleagues.Add(colleague2);

colleague1.Send(“Hello from colleague 1”);

colleague2.Send(“Hello from colleague 2”);

Console.Read();

}

}

Listing 4

Memento design pattern: It helps to save the object internal state in an external place enabling us to restore the state later when needed. The memento pattern doesn’t violate encapsulation of the internal state. The pattern is rarely used but it’s very helpful in scientific computing or in computer games.

It’s mainly used when you need to save object’s state and use the saved state later in order to restore the saved state and you don’t want to expose the internal state of your object (see Figure 5).

05

Figure 5

An example code for this pattern is shown in the Listing 5.

public class Originator<T>

{

public T State { get; set; }

public Memento<T> SaveMemento()

{

return (new Memento<T>(State));

}

public void RestoreMemento(Memento<T> memento)

{

State = memento.State;

}

}

 

public class Memento<T>

{

public T State { get; private set; }

public Memento(T state)

{

State = state;

}

}

 

public class Caretaker<T>

{

public Memento<T> Memento { get; set; }

}

 

class Program

{

static void Main(string[] args)

{

Originator<string> org = new Originator<string>();

org.State = “Old State”;

Caretaker<string> caretaker = new Caretaker<string>();

caretaker.Memento = org.SaveMemento();

Console.WriteLine(“This is the old state: {0}”, org.State);

org.State = “New state”;

Console.WriteLine(“This is the new state: {0}”, org.State);

org.RestoreMemento(caretaker.Memento);

Console.WriteLine(“Old state was restored: {0}”, org.State);

Console.Read();

}

}

Listing 5

Observer design pattern: It is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.

You mainly use this pattern when you have a publisher/subscriber model, objects need to be notified of a change in another objects, and you need that the object that notify its state change would not know about its subscribers.

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

06

Figure 6

An example code for this design pattern is shown in the Listing 6.

public abstract class Subject

{

private List<IObserver> _observers;

 

public Subject()

{

_observers = new List<IObserver>();

}

 

public void Attach(IObserver observer)

{

_observers.Add(observer);

}

 

public void Detach(IObserver observer)

{

_observers.Remove(observer);

}

 

public void Notify()

{

foreach (IObserver observer in _observers)

{

observer.Update();

}

}

}

 

public class ConcreteSubject<T> : Subject

{

public T SubjectState { get; set; }

}

 

public interface IObserver

{

void Update();

}

 

public class ConcreteObserver<T> : IObserver

{

private T _observerState;

public ConcreteObserver(ConcreteSubject<T> subject)

{

Subject = subject;

}

 

public void Update()

{

_observerState = Subject.SubjectState;

Console.WriteLine(“The new state of the observer:{0}”, _observerState.ToString());

}

}

 

class Program

{

static void Main(string[] args)

{

ConcreteSubject<string> subject = new ConcreteSubject<string>();

subject.Attach(new ConcreteObserver<string>(subject));

subject.Attach(new ConcreteObserver<string>(subject));

subject.SubjectState = “Hello World”;

subject.Notify();

System.Console.Read();

}

}

Listing 6

Strategy design pattern: It allows you to use multiple algorithms interchangeably.  One reason you might use a Strategy design pattern is to simplify an overly complex algorithm. Sometimes, as an algorithm evolves to handle more and more situations, it can become very complex and difficult to maintain. Breaking these complex algorithms down into smaller more manageable algorithms might make your code more readable and more easily maintained.

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

07

Figure 7

An example code for this design pattern is shown in the Listing 7.

using System;

 

namespace Wikipedia.Patterns.Strategy

{

class MainApp

{

static void Main()

{

Context anObject;

 

// Three contexts following different strategies

anObject = new Context(new ConcreteStrategyA());

anObject.Execute();

 

anObject.UpdateContext(new ConcreteStrategyB());

anObject.Execute();

 

anObject.UpdateContext(new ConcreteStrategyC());

anObject.Execute();

}

}

 

interface IStrategy

{

void Execute();

}

 

class ConcreteStrategyA : IStrategy

{

public void Execute()

{

Console.WriteLine(“Called ConcreteStrategyA.Execute()”);

}

}

 

class ConcreteStrategyB : IStrategy

{

public void Execute()

{

Console.WriteLine(“Called ConcreteStrategyB.Execute()”);

}

}

 

class ConcreteStrategyC : IStrategy

{

public void Execute()

{

Console.WriteLine(“Called ConcreteStrategyC.Execute()”);

}

}

 

class Context

{

IStrategy strategy;

 

public Context(IStrategy strategy)

{

this.strategy = strategy;

}

 

public void UpdateContext(IStrategy strategy)

{

this.strategy = strategy;

}

 

public void Execute()

{

strategy.Execute();

}

}

}

Listing 7

Conclusion

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