25,责任链模式
25.1,问题引入_采购需求
- 采购员需要采购一批教学器材,对器材采购金额有分级审批权限
- 如果金额小于等于3000元,由教学主任审批(0 < x <= 3000)
- 如果金额小于等于10000元,由院长审批(3000 < x <= 10000)
- 如果金额大于10000元,由校长审批(x > 10000)
- 在传递方案中,拿到采购金额后,根据金额不同,推送到不同的处理人进行处理
- 客户端需要进行更多的逻辑分支处理,调用不同的审批人进行审批
- 如果各个级别的审批金额发生变化,客户端需要同步调整
- 客户端必须明确知道,有多少个审批级别和访问
- 这样对于采购请求和审批人之间就存在强耦合,不利于系统扩展
- 可以通过职责链模式进行解耦实现
25.2,基本介绍
- 职责链模式(Chain of Responsibility Pattern):又叫责任链模式,为请求创建一个接收者对象的链。这种模式对请求的发送者和接收者进行解耦
- 职责链模式中通常一个接收者会持有另外一个接收者的引用,如果这个接收者不能处理,则会调用下一个接收者继续进行处理,直接处理或者无法处理为止,以此类推
- 职责链模式是行为型模式的一种
25.3,类图
Approver
:接收者顶层抽象类,定义接收者链并抽象化请求接收方式XXXApprover
:具体接收者类,进行请求处理,当无法处理时,调用下一个接收者nextApprover
进行处理Request
:接收者需要处理的请求,用户进行事件传递
25.4,代码实现
-
Approver
:接收者顶层抽象类package com.self.designmode.chain; /** * 职责链模式: 顶层抽象类, 定义责任链及请求处理方式的抽象类 * @author PJ_ZHANG * @create 2020-12-18 11:33 **/ public abstract class Approver { /** * 下一个处理器 */ private Approver nextApprover; public Approver getNextApprover() { return nextApprover; } public void setNextApprover(Approver nextApprover) { this.nextApprover = nextApprover; } /** * 事件处理的抽象类 * @param request */ public abstract void processRequest(Request request); }
-
DepartmentApprover
:主任接收者处理package com.self.designmode.chain; import com.self.designmode.iterator.Department; /** * 职责链模式: 主任处理器 * @author PJ_ZHANG * @create 2020-12-18 11:36 **/ public class DepartmentApprover extends Approver { private String name; public DepartmentApprover(String name) { this.name = name; } @Override public void processRequest(Request request) { if (request.getPrice() <= 3000) { System.out.println("主任处理完成: " + request.getPrice()); } else { getNextApprover().processRequest(request); } } }
-
CollegeApprover
:院长接收者处理package com.self.designmode.chain; /** * 职责链模式: 院长处理器 * @author PJ_ZHANG * @create 2020-12-18 11:36 **/ public class CollegeApprover extends Approver { private String name; public CollegeApprover(String name) { this.name = name; } @Override public void processRequest(Request request) { if (request.getPrice() > 3000 && request.getPrice() <= 10000) { System.out.println("院长处理完成: " + request.getPrice()); } else { getNextApprover().processRequest(request); } } }
-
SchoolMasterApprover
:校长接收者处理package com.self.designmode.chain; /** * 职责链模式: 院长处理器 * @author PJ_ZHANG * @create 2020-12-18 11:36 **/ public class SchoolMasterApprover extends Approver { private String name; public SchoolMasterApprover(String name) { this.name = name; } @Override public void processRequest(Request request) { if (request.getPrice() > 10000) { System.out.println("校长处理完成: " + request.getPrice()); } else { getNextApprover().processRequest(request); } } }
-
Request
:职业链处理事件package com.self.designmode.chain; /** * 责任链模式: 处理请求, 即需要处理的时间 * @author PJ_ZHANG * @create 2020-12-18 11:34 **/ public class Request { /** * 根据不同的价格, 选择不同的处理器进行处理 */ private Integer price; public Request(Integer price) { this.price = price; } public Integer getPrice() { return price; } public void setPrice(Integer price) { this.price = price; } }
-
Client
:客户端package com.self.designmode.chain; /** * 职责链模式: 客户端 * @author PJ_ZHANG * @create 2020-12-18 11:40 **/ public class Client { public static void main(String[] args) { // 创建一个请求 Request request = new Request(1500000); // 构建职责链 DepartmentApprover departmentApprover = new DepartmentApprover("主任"); CollegeApprover collegeApprover = new CollegeApprover("院长"); SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("校长"); departmentApprover.setNextApprover(collegeApprover); collegeApprover.setNextApprover(schoolMasterApprover); // 这部分为了构成环状, 不让请求走空, 这部分可以走一个空实现 schoolMasterApprover.setNextApprover(departmentApprover); // 处理, 从主任开始 departmentApprover.processRequest(request); } }
25.5,职责链模式的注意事项和细节
- 将请求和处理分开,实现解耦,提高系统的灵活性
- 简化了对象,使对象不需要知道链的结构,只需要传递下一个执行者执行
- 在链比较长的时候,性能会受到影响,在链中节点数量过多时,应该添加限制
- 调试困难,整个代码调用类似于过多递归,造成调试难度
- 应用场景:在多个拦截器处理一个请求的时候,如多级请求、请假加薪等审批流程。Tomcat的启动初始化完全贯彻了责任链模式。