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:
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:
UML Diagram:
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:
UML Diagram:
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:
UML Diagram:
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:
UML Diagram:
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:
UML Diagram:
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...