定义
Chain of Responsibility Pattern:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链, 并沿着这条链传递该请求,直到有对象处理它为止。
优势
-
解耦请求发送者与接收者,发送者无需知道具体由哪个对象处理请求;
-
新增处理者时只需加入链条,无需修改原有代码,符合 "开闭原则"。
场景
生活场景
最典型的例子是 公司请假审批流程:
-
请假 1 天以内:组长直接审批;
-
请假 1-3 天:组长无权处理,传递给部门经理审批;
-
请假 3 天以上:部门经理无权处理,传递给总经理审批。
这里,组长→部门经理→总经理形成一条 "责任链",请假请求会沿着链条传递,直到被对应的负责人处理。
Java 中的责任链场景
-
Servlet Filter 链:
客户端请求经过多个 Filter(过滤器)处理(如编码过滤、权限校验、日志记录等),每个 Filter 可选择处理请求后传递给下一个 Filter,或直接终止请求。
-
Spring Interceptor 链:
Spring MVC 中的拦截器链,对请求进行预处理(如登录验证)、后处理(如数据封装),每个 Interceptor 可决定是否继续传递请求。
-
异常处理机制:
Java 的异常捕获(try-catch)本质上也是责任链:异常会从发生处向上传递,直到被第一个匹配的 catch 块处理。
代码
java
// 抽象审批者类:定义责任链节点的通用行为
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 {
@Override
public 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 {
@Override
public 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 {
@Override
public 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);
}
}