Friday, July 16, 2010

Design Patterns: Chain of Responsibility

It is one of those design patterns that have a very fundamental idea but their usage under this specific title is limited. The idea of the pattern which converges with other design patterns is that we have to decouple a "Requester" from a specific "Handler" by introducing a chain of handlers that are derived from a parent "handler" class. As the request "bubbles up" a chain of handlers, eventually it will be handled by one of them.

A classic example is an "Approval" that has to be obtained from a certain office. As the client turns in his request for the approval, it starts to travel from employee to his boss and then to the boss's boss etc... until someone in this chain is in a position to approve the request.

Major Players of this pattern are:

  • Handler (The abstract Employee)

  • Real Handlers (The main players - Programmer, Manager, CEO)

  • Client



The idea is common as part of the Windows event handling mechanism. For example UI programmers have noticed different UI events (Painting event) that are bubbled up along the chain of parent-child windows, until one of them handles it.


class Program
{
static void Main(string[] args)
{
// Setup Chain of Responsibility
Employee h1 = new Programmer();
Employee h2 = new Manager();
Employee h3 = new CEO();
h1.SetBoss(h2);
h2.SetBoss(h3);

// Generate and process request
int[] inquiries = { 1, 2, 3, 3, 2, 4, 1, 1 };

foreach (int inquiry in inquiries)
{
h1.Approve(inquiry);
}

// Wait for user
Console.Read();
}
}

abstract class Employee
{
protected Employee Boss;

public void SetBoss(Employee boss)
{
this.Boss = boss;
}

public abstract void Approve(int inquiry);
}

class Programmer : Employee
{
public override void Approve(int inquiry)
{
if (inquiry <= 1)
{
Console.WriteLine("Inquiry approved by the employee");
}
else if (Boss != null)
{
Boss.Approve(inquiry);
}
}
}

class Manager : Employee
{
public override void Approve(int inquiry)
{
if (inquiry <= 2)
{
Console.WriteLine("Inquiry approved by the manager");
}
else if (Boss != null)
{
Boss.Approve(inquiry);
}
}
}

class CEO : Employee
{
public override void Approve(int inquiry)
{
Console.WriteLine("Inquiry approved by the CEO");
}
}

No comments:

Post a Comment