模式定义
责任链模式(Chain of Responsibility): 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条对象连成一条链,并沿着这条链传递请求。
UML类图
- 抽象处理者(Handler) :定义一个处理请求的接口。聚合自己类型,用来设置请求的处理的下家对象。
- 具体处理者(Concrete Handler): 实现请求方法,处理掉或者传递给下家对象。
客户端(Client):设置处理链,并调用。
代码结构
class ChainClient { public void Run() { Handler h1 = new ConcreteHandler1(); Handler h2 = new ConcreteHandler2(); Handler h3 = new ConcreteHandler3(); h1.SetSuccessor(h2); h2.SetSuccessor(h3); int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 }; foreach (int request in requests) { h1.HandleRequest(request); } Console.ReadKey(); } } abstract class Handler { protected Handler successor; public void SetSuccessor(Handler successor) { this.successor = successor; } public abstract void HandleRequest(int request); } class ConcreteHandler1 : Handler { public override void HandleRequest(int request) { if (request >= 0 && request < 10) { Console.WriteLine("{0} handled request {1}",this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } class ConcreteHandler2 : Handler { public override void HandleRequest(int request) { if (request >= 10 && request < 20) { Console.WriteLine("{0} handled request {1}",this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } class ConcreteHandler3 : Handler { public override void HandleRequest(int request) { if (request >= 20 && request < 30) { Console.WriteLine("{0} handled request {1}",this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } }
情景案例
这里以大学中请假为例:少于2天班长处理,少5天指导员处理,少于30天系主任处理,大于30天不允许。
class RealWorldChainClient { public void Run() { Approver h1 = new Monitor(); Approver h2 = new Instructor(); Approver h3 = new DepartmentHead(); h1.SetSuccessor(h2); h2.SetSuccessor(h3); int[] requests = { 2, 5, 14, 35 }; foreach (int request in requests) { h1.HandleRequest(request); } Console.ReadKey(); } } abstract class Approver { protected Approver successor; public void SetSuccessor(Approver successor) { this.successor = successor; } public abstract void HandleRequest(int days); } /// <summary> /// 班长 /// </summary> class Monitor : Approver { public override void HandleRequest(int days) { if (days >= 0 && days <= 2) { Console.WriteLine("我是班长,批准请假{0}天",days); } else if (successor != null) { successor.HandleRequest(days); } } } /// <summary> /// 指导员 /// </summary> class Instructor : Approver { public override void HandleRequest(int days) { if (days >= 0 && days < 10) { Console.WriteLine("我是指导员,批准请假{0}天", days); } else if (successor != null) { successor.HandleRequest(days); } } } /// <summary> /// 系主任 /// </summary> class DepartmentHead : Approver { public override void HandleRequest(int days) { if (days >= 0 && days < 30) { Console.WriteLine("我是指导员,批准请假{0}天", days); } else { Console.WriteLine("请假天数太多了,退学吧!"); } } }
自问自答
小a:你的博客好冷清呀!!!我感觉你上面将的例子还不如用
if()....else....
简单明了,整那么多类倒是增加了复杂性,感觉真个模式没必要?
LoveTomato: 啊!!!确实博客比较冷清,万事开头难吗?开头难也要开头的吗。
回答正题 确实业务比较简单,顺序编程简单快捷。但是项目中往往有比较复杂的,如好多网站有需要用户填入的表单,后台验证数据的有效性。假设验证的指标有
- 必填性验证
- 数据类型验证(时间类型的值是否有效等)
- 业务验证(需要查询数据库)
这样每个验证都需要大段的代码,在if...else
中维护的心情你懂的,而且每次添加项新的验证都需要修改if...else
。