Behavioral Design Pattern for .NET: Part 1


BEHAVIORAL: Behavioral Design patterns are the patterns for .Net in which there is a way through which we can pass the request between the chain of objects, or we can say that it defines the manner to communicate between classes and object.

Behavioral Patterns are Categorized as under:

DesPatte1.gif


1. Chain Of Responsibility:

In this pattern there is a single chain of passing a request with many handlers. Each sender keeps a single reference to the head of the chain, and each receiver keeps a single reference to its immediate successor in the chain. This pattern is used to process those requests that are varied.

Model:

DesPatte2.gif

UML Diagram:

DesPatte3.gif

Example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace chainofResposibility
{
  class Example
   {
    static void Main()
     {
      Approver Sameer = new President();
      Approver Abhi = new CEO();
      Approver Rahul = new Manager();

      Rahul.SetSuccessor(Sameer);
      Sameer.SetSuccessor(Abhi);

      

      // Generate and process purchase requests
      Project p = new Project(3333, 350.00, "Test Postponed");
      Rahul.ProcessRequest(p);
      p = new Project(5353, 32590.10, "Annual Function");
      Rahul.ProcessRequest(p);
      p = new Project(2036, 122100.00, "Renovation of Classes");
      Rahul.ProcessRequest(p);

      Console.ReadKey();
    }
 }


//Handler  abstract class 
 
abstract class Approver
 {
  protected Approver successor;
  public void SetSuccessor(Approver successor)
   {
    this.successor = successor;
   }
  public abstract void ProcessRequest(Project Project);
 }


//ConcreteHandler  class
 
class Manager : Approver
  {
   public override void ProcessRequest(Project Project)
   {
    if (Project.Amount < 10000.0)
     {
      Console.WriteLine("{0} approved request# {1}",
      this.GetType().Name, Project.Number);
     }
      else if (successor != null)
      {
       successor.ProcessRequest(Project);
      }
    }
  }

class President : Approver
 {
  public override void ProcessRequest(Project Project)
   {
    if (Project.Amount < 25000.0)
     {
      Console.WriteLine("{0} approved request# {1}",
      this.GetType().Name, Project.Number);
     }
      else if (successor != null)
      {
        successor.ProcessRequest(Project);
      }
    }
  }

class CEO : Approver
 {
  public override void ProcessRequest(Project Project)
   {
    if (Project.Amount < 100000.0)
     {
      Console.WriteLine("{0} approved request# {1}",
      this.GetType().Name, Project.Number);
     }
      else
      {
       Console.WriteLine(
       "Request# {0} requires an executive meeting!",
       Project.Number);
      }
    }
  }

// Class holding request details
class
Project
 {
  private int _number;
  private double _amount;
  private string _purpose;

// Constructor 
public Project(int number, double amount, string purpose)
   {
    this._number = number;
    this._amount = amount;
    this._purpose = purpose;
   }
  public int Number
   {
    get { return _number; }
    set { _number = value; }
   }
  public double Amount
   {
    get { return _amount; }
    set { _amount = value; }
   }
  public string Purpose
   {
    get { return _purpose; }
    set { _purpose = value; }
   }
 }
}


2. Command:

To call a method later we need some information like method name, its object and its values, to represent that information command pattern is used. It allows a request to be saved in a queue. The Command pattern has three main components: the Invoker, the Command, and the Receiver. Here is an example of Chat application:

Model:

DesPatte4.gif


UML Diagram:

DesPatte5.gif

Example:

using System;
using System.Collections.Generic;

namespace Command
 class Example
  {
   static void Main()
    {
     User user = new User();         // Creating User 

            // User presses calculator buttons

          user.Compute('+', 100);
          user.Compute('-', 50);
          user.Compute('*', 10);
          user.Compute('/', 2);
          user.Undo(4);
          user.Redo(3);
          Console.ReadKey();
    }
  }
   abstract class Command
    {
     public abstract void Execute();
     public abstract void UnExecute();
    }

    //ConcreteCommand' class
    class CalculatorCommand : Command
    {
     private char _operator;
     private int _operand;
     private Calculator _calculator;

     

     // Constructor
     public CalculatorCommand(Calculator calculator,
     char @operator, int operand)
        {
         this._calculator = calculator;
         this._operator = @operator;
         this._operand = operand;
        }
      public char Operator
        {
         set { _operator = value; }
        }
      public int Operand
        {
         set { _operand = value; }
        }

      // Execute new command

      public override void Execute()
        {
         _calculator.Operation(_operator, _operand);
        }

      // Unexecute last command
      public override void UnExecute()
        {
         _calculator.Operation(Undo(_operator), _operand);
        }
      private char Undo(char @operator)
        {
         switch (@operator)
          {
           case '+': return '-';
           case '-': return '+';
           case '*': return '/';
           case '/': return '*';
           default: throw new
           ArgumentException("@operator");
          }
        }
    }

// The 'Receiver' class 
 class Calculator
  {
   private int _curr = 0;
   public void Operation(char @operator, int operand)
    {
     switch (@operator)
       {
        case '+': _curr += operand; break;
        case '-': _curr -= operand; break;
        case '*': _curr *= operand; break;
        case '/': _curr /= operand; break;
       }
     Console.WriteLine(
     "Current value = {0,3} (following {1} {2})",
       _curr, @operator, operand);
    }
 }

// The 'Invoker' class  
class User
  {
   private Calculator _calculator = new Calculator();
   private List<Command> _commands = new List<Command>();
   private int _current = 0;
   public void Redo(int levels)
    {
     Console.WriteLine("\n---- Redo {0} levels ", levels);
       for (int i = 0; i < levels; i++)
        {
         if (_current < _commands.Count - 1)
           {
             Command command = _commands[_current++];
             command.Execute();
           }
        }
    }

   public void Undo(int levels)
    {
     Console.WriteLine("\n---- Undo {0} levels ", levels);
       for (int i = 0; i < levels; i++)
        {
         if (_current > 0)
           {
             Command command = _commands[--_current] as Command;
             command.UnExecute();
           }
        }
    }
    public void Compute(char @operator, int operand)
     {
      // Create command operation and execute it
      Command command = new CalculatorCommand(
      _calculator, @operator, operand);
      command.Execute();

      // Add command to undo list 
      _commands.Add(command);
      _current++;
     }
    }
}



3. Interpreter:

Interpreter pattern defines how the communication between the entities is controlled in a good manner and also defines the instructions grammar. The interpreter design pattern is useful for simple languages where performance is not critical.

Model:

DesPatte6.gif

UML Diagram:

DesPatte7.gif

Example:

using System;
using System.Collections.Generic;

namespace Interpreter
{
 class Example
  {
   static void Main()
    {
     string roman = "MCMXXVIII";
     Context context = new Context(roman);

      // Build the 'parse tree'
     List<Expression> tree = new List<Expression>();
     tree.Add(new ThousandExpression());
     tree.Add(new HundredExpression());
     tree.Add(new TenExpression());
     tree.Add(new OneExpression());

     foreach (Expression exp in tree)
      {
       exp.Interpret(context);
      }
       Console.WriteLine("{0} = {1}",
       roman, context.Output);
       Console.ReadKey();
    }
  }

class Context
 {
  private string _input;
  private int _output;
  public Context(string input)
   {
    this._input = input;
   }
  public string Input
   {
    get { return _input; }
    set { _input = value; }
   }
  public int Output
   {
    get { return _output; }
    set { _output = value; }
   }
 }

//'AbstractExpression'  class
abstract class Expression
 {
  public void Interpret(Context context)
   {
    if (context.Input.Length == 0)
    return;
    if (context.Input.StartsWith(Nine()))
     {
      context.Output += (9 * Multiplier());
      context.Input = context.Input.Substring(2);
     }
    else if (context.Input.StartsWith(Four()))
     {
      context.Output += (4 * Multiplier());
      context.Input = context.Input.Substring(2);
     }
    else if (context.Input.StartsWith(Five()))
     {
      context.Output += (5 * Multiplier());
      context.Input = context.Input.Substring(1);
     }
    while (context.Input.StartsWith(One()))
     {
      context.Output += (1 * Multiplier());
      context.Input = context.Input.Substring(1);
     }
   }

    public abstract string One();
    public abstract string Four();
    public abstract string Five();
    public abstract string Nine();
    public abstract int Multiplier();
 }
 class ThousandExpression : Expression
 {
  public override string One() { return "M"; }
  public override string Four() { return " "; }
  public override string Five() { return " "; }
  public override string Nine() { return " "; }
  public override int Multiplier() { return 1000; }
 }
 class HundredExpression : Expression
 {
  public override string One() { return "C"; }
  public override string Four() { return "CD"; }
  public override string Five() { return "D"; }
  public override string Nine() { return "CM"; }
  public override int Multiplier() { return 100; }
 }
 class TenExpression : Expression
 {
  public override string One() { return "X"; }
  public override string Four() { return "XL"; }
  public override string Five() { return "L"; }
  public override string Nine() { return "XC"; }
  public override int Multiplier() { return 10; }
 }
 class OneExpression : Expression
 {
  public override string One() { return "I"; }
  public override string Four() { return "IV"; }
  public override string Five() { return "V"; }
  public override string Nine() { return "IX"; }
  public override int Multiplier() { return 1; }
 }
}


4. Iterator:

This pattern is used to provide the way to access the aggregate object without any knowledge of Aggregate structure. The iterator object will maintain the state of the iteration, keeping track of the current item and having a way of identifying what elements are next to be iterated. This allows traversing of lists, trees and other structures in a standard manner.

Model:

DesPatte8.gif

UML Diagram:

DesPatte9.gif

Example:

using System;
using System.Collections;

namespace Iterator
{
 class Example
  {
   static void Main()
    {
      // Build a collection
     Collection collection = new Collection();
     collection[0] = new Item("Item A");
     collection[1] = new Item("Item B");
     collection[2] = new Item("Item C");
     collection[3] = new Item("Item D");
     collection[4] = new Item("Item E");
     collection[5] = new Item("Item F");
     collection[6] = new Item("Item G");
     collection[7] = new Item("Item H");
     collection[8] = new Item("Item I");

      Iterator iterator = new Iterator(collection);
     iterator.Step = 2;
     Console.WriteLine("Iterating over collection:");
       for (Item item = iterator.First();
         !iterator.IsDone; item = iterator.Next())
           {
            Console.WriteLine(item.Name);
           }
            Console.ReadKey();
        }
    }

 class Item
  {
   private string _name;
   public Item(string name)
    {
     this._name = name;
    }
   public string Name
    {
     get { return _name; }
    }
  }

//The 'Aggregate' interface
 interface IAbstractCollection
  {
   Iterator CreateIterator();
  }

 class Collection : IAbstractCollection
  {
   private ArrayList _items = new ArrayList();
   public Iterator CreateIterator()
    {
     return new Iterator(this);
    }
   public int Count
   {
       get { return _items.Count; }
   }
     public object this[int index]
      {
       get { return _items[index]; }
       set { _items.Add(value); }
      }
     }

//The 'Iterator' interface
  interface IAbstractIterator
   {
    Item First();
    Item Next();
    bool IsDone { get; }
    Item CurrentItem { get; }
   }

 class Iterator : IAbstractIterator
   {
    private Collection _collection;
    private int _current = 0;
    private int _step = 1;
    public Iterator(Collection collection)
      {
       this._collection = collection;
      }
    public Item First()
      {
       _current = 0;
       return _collection[_current] as Item;
      }
    public Item Next()
      {
       _current += _step;
       if (!IsDone)
       return _collection[_current] as Item;
       else
       return null;
      }
    public int Step
      {
       get { return _step; }
       set { _step = value; }
      }
    public Item CurrentItem
      {
       get { return _collection[_current] as Item; }
      }
    public bool IsDone               // Gets whether iteration is complete
      {
       get { return _current >= _collection.Count; }
      }
   }
}


5. Mediator:

Mediator design pattern also deals with communication and defines an object to encapsulate that how the set of an object should interact. It promotes many–to–many relationships between interacting peers and thus defines simplifies communication between classes. Here is an example of text box with buttons.

Model:

DesPatte10.gif

UML Diagram:

DesPatte11.gif

Example:

using System;
using System.Collections.Generic;

namespace Mediator
{
 class Example
  {
   static void Main()
    {
     Chatroom chatroom = new Chatroom();            // Create chatroom

      // Create participants and register them 

       Participant AlkaYagnik = new Singer("AlkaYagnik");
       Participant Abhijeet = new Singer("Abhijeet");
       Participant Sunidhi = new Singer("Sunidhi");
       Participant Shaan = new Singer("Shaan");
       Participant Abhishek = new NonSinger("Abhishek");
         chatroom.Register(AlkaYagnik);
         chatroom.Register(Abhijeet);
         chatroom.Register(Sunidhi);
         chatroom.Register(Shaan);
         chatroom.Register(Abhishek);

       Abhishek.Send("Shaan", "Hi Shaan!");
       Abhijeet.Send("Sunidhi", "Can you sing a new Song");
       Sunidhi.Send("AlkaYagnik", "My Pleasure");
       Abhijeet.Send("Shaan", "Sorry Can't Sing");
       Shaan.Send("Abhishek", "Oh! What a Joke");
         Console.ReadKey();
      }
    }

 abstract class AbstractChatroom
    {
     public abstract void Register(Participant participant);
     public abstract void Send(
     string from, string to, string message);
    }

//The 'ConcreteMediator' class
 class Chatroom : AbstractChatroom
    {
     private Dictionary<string, Participant> _participants =
     new Dictionary<string, Participant>();
     public override void Register(Participant participant)
      {
       if (!_participants.ContainsValue(participant))
        {
         _participants[participant.Name] = participant;
        }
         participant.Chatroom = this;
      }
     public override void Send(
     string from, string to, string message)
      {
       Participant participant = _participants[to];
       if (participant != null)
        {
         participant.Receive(from, message);
        }
      }
    }

 class Participant
   {
    private Chatroom _chatroom;
    private string _name;
    public Participant(string name)
     {
      this._name = name;
     }
    public string Name
     {
      get { return _name; }
     }
    public Chatroom Chatroom
     {
      set { _chatroom = value; }
      get { return _chatroom; }
     }
    public void Send(string to, string message)
     {
      _chatroom.Send(_name, to, message);
     }

    // Receives message from given participant
    public virtual void Receive(
    string from, string message)
     {
      Console.WriteLine("{0} to {1}: '{2}'",
      from, Name, message);
     }
   }

 class Singer : Participant
  {
   public Singer(string name)
   : base(name)
    {   }
   public override void Receive(string from, string message)
    {
     Console.Write("To a Singer: ");
     base.Receive(from, message);
    }
  }

//A 'ConcreteColleague' class 
class NonSinger : Participant
  {
   public NonSinger(string name)
   : base(name)
    {   }
   public override void Receive(string from, string message)
    {
     Console.Write("To a non-Singer: ");
     base.Receive(from, message);
    }
  }
}


Continue...