设计模式9-责任链模式
定义
Chain of Responsibility Pattern:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链, 并沿着这条链传递该请求,直到有对象处理它为止。
优势
-
解耦请求发送者与接收者,发送者无需知道具体由哪个对象处理请求;
-
新增处理者时只需加入链条,无需修改原有代码,符合 “开闭原则”。
场景
生活场景
最典型的例子是 公司请假审批流程:
-
请假 1 天以内:组长直接审批;
-
请假 1-3 天:组长无权处理,传递给部门经理审批;
-
请假 3 天以上:部门经理无权处理,传递给总经理审批。
这里,组长→部门经理→总经理形成一条 “责任链”,请假请求会沿着链条传递,直到被对应的负责人处理。
Java 中的责任链场景
-
Servlet Filter 链:
客户端请求经过多个 Filter(过滤器)处理(如编码过滤、权限校验、日志记录等),每个 Filter 可选择处理请求后传递给下一个 Filter,或直接终止请求。 -
Spring Interceptor 链:
Spring MVC 中的拦截器链,对请求进行预处理(如登录验证)、后处理(如数据封装),每个 Interceptor 可决定是否继续传递请求。 -
异常处理机制:
Java 的异常捕获(try-catch)本质上也是责任链:异常会从发生处向上传递,直到被第一个匹配的 catch 块处理。
代码
// 抽象审批者类:定义责任链节点的通用行为
abstract class Approver {protected Approver nextApprover; // 下一个审批者(责任链的下一个节点)// 设置下一个审批者public void setNextApprover(Approver nextApprover) {this.nextApprover = nextApprover;}// 抽象处理方法:子类需实现具体审批逻辑public abstract void handleRequest(LeaveRequest request);
}// 请假请求类:封装请求信息class LeaveRequest {private String name; // 申请人姓名private int days; // 请假天数public LeaveRequest(String name, int days) {this.name = name;this.days = days;}// getter方法public String getName() {return name;}public int getDays() {return days;}
}// 组长:处理1天以内的请假class GroupLeader extends Approver {@Overridepublic void handleRequest(LeaveRequest request) {if (request.getDays() <= 1) {System.out.println("组长批准 " + request.getName() + " 请假" + request.getDays() + "天");} else {// 超过权限,传递给下一个审批者if (nextApprover != null) {nextApprover.handleRequest(request);}}}
}// 总经理:处理3天以上的请假
class GeneralManager extends Approver {@Overridepublic void handleRequest(LeaveRequest request) {if (request.getDays() > 3) {System.out.println("总经理批准 " + request.getName() + " 请假" + request.getDays() + "天");} else {// 超过权限,传递给下一个审批者(此处为链的终点,可省略)if (nextApprover != null) {nextApprover.handleRequest(request);}}}
}// 部门经理:处理1-3天的请假class DeptManager extends Approver {@Overridepublic void handleRequest(LeaveRequest request) {if (request.getDays() > 1 && request.getDays() <= 3) {System.out.println("部门经理批准 " + request.getName() + " 请假" + request.getDays() + "天");} else {// 超过权限,传递给下一个审批者if (nextApprover != null) {nextApprover.handleRequest(request);}}}
}// 测试类:构建责任链并模拟请假请求
class Client {public static void main(String[] args) {// 创建审批者Approver groupLeader = new GroupLeader();Approver deptManager = new DeptManager();Approver generalManager = new GeneralManager();// 构建责任链:组长→部门经理→总经理groupLeader.setNextApprover(deptManager);deptManager.setNextApprover(generalManager);// 模拟请假请求LeaveRequest request1 = new LeaveRequest("张三", 1); // 1天:组长处理LeaveRequest request2 = new LeaveRequest("李四", 2); // 2天:部门经理处理LeaveRequest request3 = new LeaveRequest("王五", 5); // 5天:总经理处理// 发送请求(从链的起点开始)groupLeader.handleRequest(request1);groupLeader.handleRequest(request2);groupLeader.handleRequest(request3);}
}
责任链模式代码