职责链模式(Chain of Responsibility)定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。也叫责任链模式。
优点:
降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点:
不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
代码背景:公司员工想要申请假期或加薪,需要领导层层审批,往往审批先交给经理,经理再往上级传递,员工不知道他的申请会传递到哪位领导手里进行审批。
管理者类:
abstract class Manager//管理者 { protected string name; //管理者上级 protected Manager superior; public Manager (string name) { this.name = name; } //设置管理者的上级 public void SetSuperior(Manager superior)//关键方法 { this.superior = superior; } //申请请求 abstract public void RequestApplications(Request request); }
经理类:
class CommonManager:Manager { public CommonManager (string name):base(name) { } public override void RequestApplications(Request request) { //经理的权限就是批准两天以内的假期 if(request.RequestType =="请假" && request.Number<=2) { Console.WriteLine("{0}:{1} 数量{2} {3}被批准", name,request.RequestContent ,request .Number, request.RequestType); } else { if (superior != null) superior.RequestApplications(request);//其余都要转到上级 } } }
总监类:
class Majordomo:Manager { public Majordomo (string name) : base(name) { } public override void RequestApplications(Request request) { //总监的权限就是批准一周以内的假期 if (request.RequestType == "请假" && request.Number <= 5) { Console.WriteLine("{0}:{1} 数量{2} {3}被批准", name, request.RequestContent, request.Number, request.RequestType); } else { if (superior != null) superior.RequestApplications(request);//其余都要转到上级 } } }
总经理类:
class CEO :Manager { public CEO (string name):base(name) { } public override void RequestApplications(Request request) { //总经理的权限就是批准任意天数的假期,加薪500以内没问题,500以上要考虑 if (request.RequestType == "请假") { Console.WriteLine("{0}:{1} 数量{2} {3}被批准", name, request.RequestContent, request.Number, request.RequestType); } else if (request.RequestType == "加薪" && request.Number <= 500) { Console.WriteLine("{0}:{1} 数量{2} {3}被批准", name, request.RequestContent, request.Number, request.RequestType); } else if (request.RequestType == "加薪" && request.Number > 500) { Console.WriteLine("{0}:{1} 数量{2} {3}在考虑考虑", name, request.RequestContent, request.Number, request.RequestType); } } }
客户端:
static void Main(string[] args) { CommonManager jingli = new CommonManager("张经理"); Majordomo zongjian = new Majordomo("李总监"); CEO ceo = new CEO("夏总"); //设置上级,可以根基实际需求来改 jingli.SetSuperior(zongjian); zongjian.SetSuperior(ceo); //新建请求 Request request = new Request(); request.RequestType = "请假"; request.RequestContent = "李亮请假"; request.Number =1; jingli.RequestApplications(request);//申请都是由经理发起,具体谁审批通过的客户不知道 request.RequestType = "请假"; request.RequestContent = "东东请假"; request.Number = 4; jingli.RequestApplications(request); request.RequestType = "加薪"; request.RequestContent = "阿强加薪"; request.Number = 500; jingli.RequestApplications(request); request.RequestType = "加薪"; request.RequestContent = "胖胖加薪"; request.Number = 1000; jingli.RequestApplications(request); Console.Read(); }