动机(Motivate):
在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少地带来请求发送者与接受者的紧耦合。
如何使请求的发送者不需要指定具体的接受者?让请求的接受者自己在运行时决定来处理请求,从而使两者解耦。
意图(Intent):
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
结构图(Struct):
适用性:
1.有多个对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
2.你想在不明确接收者的情况下,向多个对象中的一个提交一个请求。
3.可处理一个请求的对象集合应被动态指定。
生活中的例子:
代码实现:
1 //Handler
2 abstract class Approver
3 {
4 protected Approver successor;
5 public void SetSuccessor(Approver successor)
6 {
7 this.successor = successor;
8 }
9 public abstract void ProcessRequest(Purchase purchase);
10
11 }
12
13
14
1 //ConcreteHandler
2 class Director :Approver
3 {
4 public override void ProcessRequest(Purchase purchase)
5 {
6 if (purchase.Amount < 10000.0)
7 {
8 Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number);
9
10 }
11 else if(successor !=null)
12 {
13 successor.ProcessRequest(purchase);
14 }
15 }
16 }
1
2
3
4 class VicePresident :Approver
5 {
6 public override void ProcessRequest(Purchase purchase)
7 {
8 if (purchase.Amount < 25000.0)
9 {
10 Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number);
11
12 }
13 else if (successor != null)
14 {
15 successor.ProcessRequest(purchase);
16 }
17 }
18 }
1
2 class President :Approver
3 {
4 public override void ProcessRequest(Purchase purchase)
5 {
6 if (purchase.Amount < 100000.0)
7 {
8 Console.WriteLine("{0} approved request# {1}", this.GetType().Name, purchase.Number);
9
10 }
11 else
12 {
13 Console.WriteLine("Request! {0} requires an executive meeting!", purchase.Number);
14 }
15 }
16 }
1
2
3 //Request details
4 class Purchase
5 {
6 private int number;
7 private double amount;
8 private string purpose;
9
10 //Constructor
11 public Purchase(int number, double amount, string purpose)
12 {
13 this.number = number;
14 this.amount = amount;
15 this.purpose = purpose;
16 }
17 //Properties
18 public double Amount
19 {
20 get { return amount; }
21 set { amount = value; }
22 }
23 public string Purpose
24 {
25 get { return purpose; }
26 set { purpose = value; }
27 }
28 public int Number
29 {
30 get { return number; }
31 set { number = value; }
32 }
33 }
客户端调用如下:
1
2 class Program
3 {
4 static void Main(string[] args)
5 {
6 //Setup Chain of Responsibility
7 Director Larry = new Director();
8 VicePresident Sam = new VicePresident();
9 President Tammy = new President();
10 Larry.SetSuccessor(Sam);
11 Sam.SetSuccessor(Tammy);
12
13 //Generate and process purchase requests
14 Purchase p = new Purchase(1034, 350.00, "Supplies");
15 Larry.ProcessRequest(p);
16
17 p = new Purchase(2035, 32590.10, "Project X");
18 Larry.ProcessRequest(p);
19
20 p = new Purchase(2036, 122100.00, "Project Y");
21 Larry.ProcessRequest(p);
22
23 //Wait for user
24 Console.Read();
25 }
26 }
运行结果如下:
Chain of Responsibility实现要点:
1.Chain of Responsibility模式的应用场合在于“一个请求可能有多个接受者,但是最后真正的接受者只胡一个”,只有这时候请求发送者与接受者的耦合才胡可能出现“变化脆弱”的症状,职责链的目的就是将二者解耦,从而更好地应对变化。
2.应用了Chain of Responsibility模式后,对象的职责分派将更具灵活性。我们可以在运行时动态添加/修改请求的处理职责。
3.如果请求传递到职责链的未尾仍得不到处理,应该有一个合理的缺省机制。这也是每一个接受对象的责任,而不是发出请求的对象的责任。