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 }