一、核心概念与定义
责任链模式是一种行为型设计模式,其核心思想是将请求沿着处理对象链传递,直到某个对象能够处理该请求为止。通过这种方式,解耦了请求的发送者与接收者,使多个对象有机会处理同一请求。
关键特点:
- 动态解耦:请求发送者无需知道具体处理者,只需将请求发送到链的起点。
- 灵活扩展:可通过动态调整链内处理者顺序或增减节点,满足开闭原则。
- 链式传递:每个处理者决定是否处理请求,否则将请求传递给下一个节点。
二、模式结构
责任链模式包含以下角色:
- 抽象处理者(Handler)
- 定义处理请求的接口,并包含对下一个处理者的引用。
- 例如:
public abstract class Handler { protected Handler next; }
。
- 具体处理者(ConcreteHandler)
- 实现抽象处理者的逻辑,判断是否处理请求。若无法处理,则调用
next.handleRequest()
传递请求。 - 例如:请假审批中的
TeamLeader
、Manager
等角色。
- 实现抽象处理者的逻辑,判断是否处理请求。若无法处理,则调用
- 客户端(Client)
- 创建处理链并发送请求,通常只需与链的起点交互。
- 例如:构造链
teamLeader.setNext(manager).setNext(director)
并调用handleRequest()
。
三、实现方式
- 链表式实现(经典方式)
通过链表维护处理者顺序,每个处理者持有下一个节点的引用:
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) { this.next = next; }
public abstract void handleRequest(Request request);
}
// 具体处理者示例(日志级别处理)
public class ErrorLogHandler extends Handler {
@Override
public void handleRequest(Request request) {
if (request.getLevel() == LogLevel.ERROR) {
System.out.println("Error: " + request.getMessage());
} else if (next != null) {
next.handleRequest(request);
}
}
}
特点:
- 适合需要动态调整链结构的场景。
- 可能因链过长导致性能下降。
- 数组式实现(优化方式)
使用数组或集合存储处理者,按顺序依次调用:
public class HandlerChain {
private List handlers = new ArrayList<>();
public void addHandler(Handler handler) { handlers.add(handler); }
public void process(Request request) {
for (Handler h : handlers) {
if (!h.handle(request)) break; // 中断式处理
}
}
}
特点:
- 更易维护,避免循环引用风险。
- 适合固定顺序的处理流程(如过滤器链)。
四、优缺点分析
优点 | 缺点 |
---|---|
解耦性:请求发送者与处理者无直接依赖。 | 请求可能未被处理:若链未覆盖所有情况,请求可能被忽略。 |
灵活性:动态增减或调整处理者顺序。 | 性能损耗:长链可能导致多次判断与传递。 |
单一职责:每个处理者仅关注自身逻辑。 | 调试复杂:链式调用可能增加调试难度。 |
五、典型应用场景
- 审批流程
- 示例:请假申请按天数由组长、经理、总监逐级审批。
teamLeader.setNext(manager).setNext(director); teamLeader.handleRequest(5); // 输出:Manager 批准了5天假期。
- 日志系统
- 按日志级别(DEBUG/INFO/ERROR)分层处理,不同级别日志由对应处理器记录。
- 过滤器链
- Web框架中的请求过滤器(如认证、日志记录、权限校验)。
- 事件处理
- 传感器信号依次经过噪声过滤、数据格式化、异常检测等处理器。
六、与其他模式的对比
- 策略模式:策略模式通过组合不同算法实现单一功能,而责任链模式通过链式传递请求。
- 命令模式:命令模式将请求封装为对象,责任链模式关注请求的传递路径。
七、总结
责任链模式通过链式处理机制,有效解耦了请求发送者与接收者,适用于需要动态分配职责或按顺序处理请求的场景。实际开发中需权衡链的长度与性能,优先选择数组式实现或结合框架(如Spring拦截器链)提升效率。