一、概述
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它通过将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求。这些处理者对象被连接成一条链,请求沿着这条链传递,直到有一个对象处理它为止。
核心思想
-
解耦:将请求的发送者和接收者解耦
-
灵活性:可以动态地重新组织和分配责任
-
多处理者:允许多个对象处理同一个请求
适用场景
-
有多个对象可以处理同一个请求,但具体由哪个对象处理需要在运行时决定
-
需要在不明确指定接收者的情况下,向多个对象中的一个提交请求
-
可动态指定一组对象处理请求
二、责任链模式结构
责任链模式主要包含以下几个角色:
-
Handler(抽象处理者):定义处理请求的接口,通常包含一个处理请求的方法和一个设置后继者的方法
-
ConcreteHandler(具体处理者):实现抽象处理者的处理方法,判断是否有能力处理该请求,如果可以则处理,否则将请求转发给后继者
-
Client(客户端):创建处理链,并向链头的具体处理者对象提交请求
三、员工请假审批系统
假设我们有一个员工请假审批系统,不同级别的领导有不同的审批权限:
-
组长:可审批1天以内的假期
-
经理:可审批3天以内的假期
-
总监:可审批7天以内的假期
-
超过7天需要CEO审批
1. 定义抽象处理者
public abstract class LeaveHandler {
protected LeaveHandler nextHandler;
// 设置下一个处理者
public void setNextHandler(LeaveHandler handler) {
this.nextHandler = handler;
}
// 处理请假请求
public abstract void handleRequest(LeaveRequest request);
}
2. 定义请假请求类
public class LeaveRequest {
private String employeeName;
private int leaveDays;
public LeaveRequest(String employeeName, int leaveDays) {
this.employeeName = employeeName;
this.leaveDays = leaveDays;
}
// getter方法
public String getEmployeeName() {
return employeeName;
}
public int getLeaveDays() {
return leaveDays;
}
}
3. 实现具体处理者
组长处理者:
public class GroupLeader extends LeaveHandler {
@Override
public void handleRequest(LeaveRequest request) {
if (request.getLeaveDays() <= 1) {
System.out.println("组长批准" + request.getEmployeeName() + "请假" + request.getLeaveDays() + "天");
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
}
经理处理者:
public class Manager extends LeaveHandler {
@Override
public void handleRequest(LeaveRequest request) {
if (request.getLeaveDays() <= 3) {
System.out.println("经理批准" + request.getEmployeeName() + "请假" + request.getLeaveDays() + "天");
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
}
总监处理者:
public class Director extends LeaveHandler {
@Override
public void handleRequest(LeaveRequest request) {
if (request.getLeaveDays() <= 7) {
System.out.println("总监批准" + request.getEmployeeName() + "请假" + request.getLeaveDays() + "天");
} else {
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
}
CEO处理者:
public class CEO extends LeaveHandler {
@Override
public void handleRequest(LeaveRequest request) {
System.out.println("CEO批准" + request.getEmployeeName() + "请假" + request.getLeaveDays() + "天");
}
}
测试类
public class LeaveSystemTest {
public static void main(String[] args) {
// 创建处理者
LeaveHandler groupLeader = new GroupLeader();
LeaveHandler manager = new Manager();
LeaveHandler director = new Director();
LeaveHandler ceo = new CEO();
// 设置责任链
groupLeader.setNextHandler(manager);
manager.setNextHandler(director);
director.setNextHandler(ceo);
// 创建请假请求
LeaveRequest request1 = new LeaveRequest("张三", 1);
LeaveRequest request2 = new LeaveRequest("李四", 4);
LeaveRequest request3 = new LeaveRequest("王五", 8);
// 提交请求
groupLeader.handleRequest(request1);
groupLeader.handleRequest(request2);
groupLeader.handleRequest(request3);
}
}
5. 输出结果
四、责任链模式变体
1. 纯与不纯的责任链模式
-
纯责任链模式:请求必须被某个处理者处理,不允许未被处理的情况
-
不纯责任链模式:请求可以被部分处理或不被任何处理者处理
2. 功能增强
可以在抽象处理者中添加更多方法,如:
// 判断是否能处理请求
protected abstract boolean canHandle(LeaveRequest request);
// 处理请求的具体逻辑
protected abstract void doHandle(LeaveRequest request);
五、责任链模式优缺点
优点
-
降低耦合度:请求发送者不需要知道具体由哪个处理者处理
-
增强灵活性:可以动态增加或修改处理链
-
简化对象:每个处理者只需关注自己责任范围内的请求
缺点
-
请求可能未被处理:如果没有配置默认处理者,请求可能到达链尾仍未被处理
-
性能问题:请求可能需要遍历整个链才能被处理
-
调试困难:请求的传递是隐式的,调试时不易跟踪
六、实际应用场景
-
Java Servlet中的Filter:多个Filter组成一个链,依次处理请求
-
Spring Security的认证流程:多个AuthenticationProvider组成认证链
-
日志系统中的多级日志处理:DEBUG → INFO → WARN → ERROR
-
异常处理:多层try-catch块可以看作责任链的一种形式
七、与其他模式的关系
-
与命令模式:责任链模式可以配合命令模式使用,将请求封装为命令对象
-
与组合模式:可以用组合模式来构建树形结构的责任链
-
与装饰器模式:两者都基于递归组合,但目的不同。装饰器模式是动态添加功能,责任链模式是传递请求
责任链模式通过将请求和处理分离,实现了请求发送者和接收者的解耦,提高了系统的灵活性。在实际开发中,合理使用责任链模式可以使代码更加清晰、易于维护和扩展。