Home
Gallery
GuestBook
SourceCode
Contact

In continuation with the series on design pattern, in which presently I going through Behavioral Patterns, today I will write about the Chain of Responsibility Pattern. You can read about rest of the patterns from the following links

  1. Strategy Pattern
  2. State Pattern
  3. Template Method Pattern

You can read about the Structural patterns from here.
You can read about the Creational patterns from here.

The Chain of Responsibility pattern deals with a list of Handler objects that limits based on the requests that they can deal with. If one object can not handle a request, then the request is passed to the next object in the chain which means by the end of the chain there can be an expected behavior or an exception. 

The following example is based on the example provided in the DoFactory website

    1 namespace PatternsConsole

    2 {

    3     class ChainOfResponsibilityPattern

    4     {

    5         // Delegate for withdrawal requests

    6         public delegate void WithdrawHandler<T, E>( T sender, E eventArgs );

    7 

    8         public class WithdrawArgs : EventArgs

    9         {

   10             public double Amount { get; set; }

   11             public int AccountNumber { get; set; }

   12         }

   13 

   14         // "Handler"

   15         abstract class Approver

   16         {

   17             public event WithdrawHandler<Approver, WithdrawArgs> Withdraw;

   18             public Approver Successor { protected get; set; }

   19 

   20             // Invoing the event

   21             public virtual void OnWithdraw( WithdrawArgs e )

   22             {

   23                 if ( Withdraw != null )

   24                 {

   25                     Withdraw( this, e );

   26                 }

   27             }

   28 

   29             public void ProcessRequest( WithDrawal withDrawal )

   30             {

   31                 OnWithdraw( new WithdrawArgs

   32                                 {

   33                                     AccountNumber = withDrawal.AccountNumber,

   34                                     Amount = withDrawal.Amount

   35                                 } );

   36             }

   37         }

   38 

   39         // "ConcreteHandler"

   40         class Clerk : Approver

   41         {

   42             public Clerk()

   43             {

   44                 // Hook up delegate to event

   45                 Withdraw += ProcessByClerk;

   46             }

   47 

   48             public void ProcessByClerk( Approver approver, WithdrawArgs e )

   49             {

   50                 if ( e.Amount < 10000 )

   51                 {

   52                     Console.WriteLine( "{0} approved withdrawal for account : {1}",

   53                         GetType().Name, e.AccountNumber );

   54                 }

   55                 else if ( Successor != null )

   56                 {

   57                     Successor.OnWithdraw( e );

   58                 }

   59             }

   60         }

   61 

   62         // "ConcreteHandler"

   63         class Officer : Approver

   64         {

   65             public Officer()

   66             {

   67                 // Hook up delegate to event

   68                 Withdraw += ProcessByOfficer;

   69             }

   70 

   71             public void ProcessByOfficer( Approver approver,

   72                 WithdrawArgs e )

   73             {

   74                 if ( e.Amount < 100000 )

   75                 {

   76                     Console.WriteLine( "{0} approved withdrawal for account : {1}",

   77                         GetType().Name, e.AccountNumber );

   78                 }

   79                 else if ( Successor != null )

   80                 {

   81                     Successor.OnWithdraw( e );

   82                 }

   83             }

   84         }

   85 

   86         // "ConcreteHandler"

   87         class Manager : Approver

   88         {

   89             public Manager()

   90             {

   91                 // Hook up delegate to event

   92                 Withdraw += ProcessByManager;

   93             }

   94 

   95             public void ProcessByManager( Approver approver, WithdrawArgs e )

   96             {

   97                 if ( e.Amount < 1000000 )

   98                 {

   99                     Console.WriteLine( "{0} approved withdrawal for account : {1}",

  100                         GetType().Name, e.AccountNumber );

  101                 }

  102                 else

  103                 {

  104                     Console.WriteLine( "Cannot be approved" );

  105                 }

  106             }

  107         }

  108 

  109         class WithDrawal

  110         {

  111             public double Amount { get; set; }

  112             public int AccountNumber { get; set; }

  113         }

  114 

  115         static void Main()

  116         {

  117             // Setup Chain of Responsibility

  118             var clerkAprover = new Clerk();

  119             var officerApprover = new Officer();

  120             var managerApprover = new Manager();

  121 

  122             clerkAprover.Successor = officerApprover;

  123             officerApprover.Successor = managerApprover;

  124 

  125             var withDrawal = new WithDrawal { AccountNumber = 1234, Amount = 1001 };

  126             clerkAprover.ProcessRequest( withDrawal );

  127 

  128             withDrawal = new WithDrawal { AccountNumber = 2345, Amount = 10000 };

  129             clerkAprover.ProcessRequest( withDrawal );

  130 

  131             withDrawal = new WithDrawal { AccountNumber = 3456, Amount = 100000 };

  132             clerkAprover.ProcessRequest( withDrawal );

  133 

  134             //Output : Clerk approved withdrawal for account : 1234

  135             //         Officer approved withdrawal for account : 2345

  136             //         Manager approved withdrawal for account : 3456

  137 

  138             Console.Read();

  139         }

  140     }

  141 }

As seen in the example there are 3 approvers for withdrawal as  a chain. The request is passed to the clerk and based on the amount the responsibility is transferred to the successive approver in the chain. We can use the chain of responsibility patter when we have more than one handler for a single request or we have a set of handler that vary dynamically.

In my next post I will be writing about the Command pattern.




Name:
E-mail:
Website:
Comment:
 
Anti Bot Image:

Insert Cancel


Subscribe

Random Photo

My Tweets


Top Posts

Source Code

The source code to this site is open-source. You can download the code from here.

Categories


Recent Blogs


Archives


Blogroll