责任链模式
为请求创建了一个接收者对象的链,可以对请求的发送者和接收者进行解耦。
该模式中通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,以此类推。
属于行为型模式。
UML图:
举个栗子:
学校OA系统的采购审批项目:需求是
1) 采购员采购教学器材
2) 如果金额 小于等于5000, 由教学主任审批 (0<=x<=5000)
3) 如果金额 小于等于10000, 由院长审批 (5000<x<=10000)
4) 如果金额 小于等于30000, 由副校长审批 (10000<x<=30000)
5) 如果金额 超过30000以上,有校长审批 ( 30000<x)
请设计程序完成采购审批项目
传统解法
我们可能会判断这个金额的范围,然后调用不同的对象,就会出现一大堆 if else。这样某个对象的处理金额有改动,我们就需要在主程序(发送请求者)改动代码,耦合性极强。
因此有了责任链模式
将所有对象共同继承一个接收者抽象类,一旦请求金额超过该对象的处理范围,该对象就自己调用下一个对象来处理,也就是每个对象都存在下一个对象 引用。
代码实现:
//请求类 public class PurchaseRequest { private int type = 0; //请求类型 private float price = 0.0f; //请求金额 private int id = 0; //构造器 public PurchaseRequest(int type, float price, int id) { this.type = type; this.price = price; this.id = id; } public int getType() { return type; } public float getPrice() { return price; } public int getId() { return id; } } public abstract class Approver { Approver approver; //下一个处理者 String name; // 名字 public Approver(String name) { // TODO Auto-generated constructor stub this.name = name; } //下一个处理者 public void setApprover(Approver approver) { this.approver = approver; } //处理审批请求的方法,得到一个请求, 处理是子类完成,因此该方法做成抽象 public abstract void processRequest(PurchaseRequest purchaseRequest); } //其他三个具体类实现跟这个是差不多,这里忽略了 public class SchoolMasterApprover extends Approver { public SchoolMasterApprover(String name) { // TODO Auto-generated constructor stub super(name); } @Override public void processRequest(PurchaseRequest purchaseRequest) { // TODO Auto-generated method stub if(purchaseRequest.getPrice() > 30000) { System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理"); }else { approver.processRequest(purchaseRequest); } } } public class Client { public static void main(String[] args) { // TODO Auto-generated method stub //创建一个请求 PurchaseRequest purchaseRequest = new PurchaseRequest(1, 31000, 1); //创建相关的审批人 DepartmentApprover departmentApprover = new DepartmentApprover("张主任"); CollegeApprover collegeApprover = new CollegeApprover("李院长"); ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("王副校"); SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("佟校长"); //需要将各个审批级别的下一个设置好 (处理人构成环形: ) departmentApprover.setApprover(collegeApprover); collegeApprover.setApprover(viceSchoolMasterApprover); viceSchoolMasterApprover.setApprover(schoolMasterApprover); schoolMasterApprover.setApprover(departmentApprover); departmentApprover.processRequest(purchaseRequest); viceSchoolMasterApprover.processRequest(purchaseRequest); } }
注意
性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在Handler中设置一个最大节点数量,在setNext()方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地破坏系统性能。
应用场景
SpringMVC在处理请求时的HandlerExecutionChain类就使用到职责链模式