责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,其核心思想是:将请求的处理者解耦,让请求沿着链传递,直到被某个处理者处理或链结束。它通过链式结构实现灵活、可扩展的请求处理逻辑,广泛应用于各种场景,如审批流程、过滤器链、拦截器链等。
一、责任链模式的核心要素
1. 请求(Request)
请求是客户端发起的事件或数据,例如:HTTP 请求、请假申请、订单校验等。
它需要被多个处理者依次处理,直到被某个处理者“终结”。
2. 处理者(Handler)
每个处理者是一个对象,负责处理请求的一部分逻辑。
处理者通常包含以下功能:
处理请求:判断是否能处理当前请求。
传递请求:如果不能处理,则将请求传递给链中的下一个处理者。
3. 链(Chain)
链是由多个处理者按顺序组成的结构。
链的构建方式可以是静态的(如配置文件)或动态的(如代码中手动拼接)。
4. 终止条件
链的终点可能是:
某个处理者处理了请求(如审批通过)。
所有处理者都无法处理请求(如拒绝审批)。
二、责任链模式的实现结构
1. 抽象处理者(Handler)
定义统一的接口,包含处理请求的方法和传递请求的方法。
// 抽象处理者接口
public interface Handler {
void setNext(Handler next); // 设置下一个处理者
void handleRequest(Request request); // 处理请求
}2. 具体处理者(Concrete Handlers)
实现具体的处理逻辑,决定是否处理请求或传递给下一个处理者。
// 具体处理者1:主管
public class Manager implements Handler {
private Handler next;
public void setNext(Handler next) {
this.next = next;
}
public void handleRequest(Request request) {
if (request.getDays() <= 1) {
System.out.println("主管批准 " + request.getName() + " 的 " + request.getDays() + " 天请假");
} else if (next != null) {
System.out.println("主管转交经理处理 " + request.getName() + " 的 " + request.getDays() + " 天请假");
next.handleRequest(request);
}
}
}
// 具体处理者2:经理
public class Manager2 implements Handler {
private Handler next;
public void setNext(Handler next) {
this.next = next;
}
public void handleRequest(Request request) {
if (request.getDays() <= 3) {
System.out.println("经理批准 " + request.getName() + " 的 " + request.getDays() + " 天请假");
} else if (next != null) {
System.out.println("经理转交总监处理 " + request.getName() + " 的 " + request.getDays() + " 天请假");
next.handleRequest(request);
}
}
}3. 客户端(Client)
构建链的结构并发送请求。
// 客户端代码
public class Client {
public static void main(String[] args) {
// 构建责任链
Handler manager = new Manager();
Handler manager2 = new Manager2();
Handler director = new Director();
manager.setNext(manager2);
manager2.setNext(director);
// 提交请求
manager.handleRequest(new Request("张三", 2)); // 经理批准
manager.handleRequest(new Request("李四", 5)); // 总监批准
manager.handleRequest(new Request("王五", 10)); // 总监拒绝
}
}三、过滤器链(Filter Chain)作为责任链模式的典型应用
在 Web 开发中,过滤器链(Filter Chain)是责任链模式的典型应用。Servlet 容器(如 Tomcat)通过过滤器链实现对请求的预处理和后处理。
1. 过滤器链的结构
每个过滤器(Filter)是一个处理者。
请求按配置顺序依次经过每个过滤器,直到目标资源(如 Servlet)。
2. 过滤器链的执行流程
请求到达:容器调用第一个过滤器的
doFilter方法。过滤器处理:
如果过滤器能处理请求(如认证通过),调用
chain.doFilter传递请求。如果不能处理(如认证失败),直接返回响应。
目标资源处理:请求到达目标资源(如 Servlet)。
响应返回:响应按相反顺序返回,依次经过每个过滤器的后续逻辑(如日志记录)。
3. 过滤器链的代码示例
// 过滤器1:认证过滤器
public class AuthFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
if (isAuthenticated(request)) {
chain.doFilter(request, response); // 传递到下一个过滤器
} else {
((HttpServletResponse) response).sendRedirect("login.jsp");
}
}
}
// 过滤器2:日志过滤器
public class LogFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
System.out.println("请求到达日志过滤器");
chain.doFilter(request, response); // 传递到下一个过滤器
System.out.println("请求处理完成");
}
}4. 过滤器链的配置(web.xml)
<filter>
<filter-name>AuthFilter</filter-name>
<filter-class>com.example.AuthFilter</filter-class>
</filter>
<filter>
<filter-name>LogFilter</filter-name>
<filter-class>com.example.LogFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>LogFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
四、责任链模式与过滤器链的对比
五、责任链模式的优缺点
优点
解耦:发送者与处理者解耦,请求的处理逻辑由链上的节点决定。
灵活扩展:可以动态添加或移除处理者,无需修改现有代码。
动态组合:可以在运行时动态调整处理者顺序。
缺点
链过长可能导致性能问题:过多的处理者会增加请求处理时间。
调试复杂:请求的处理路径可能难以追踪(尤其在多个处理者嵌套时)。
六、责任链模式的实际应用场景
审批流程
请假、报销等请求按层级传递,直到被某个审批人处理。
示例:主管 → 经理 → 总监。
事件处理系统
GUI 事件(如点击、键盘输入)按层级传递,直到被某个组件处理。
业务规则校验
订单验证、支付校验等,按规则顺序检查,直到满足条件或失败。
Web 过滤器链
对请求进行预处理(如认证、日志)和后处理(如响应编码)。
七、责任链模式的设计原则
单一职责原则
每个处理者只关注自己的职责,避免逻辑混杂。
开闭原则
可以通过新增处理者扩展功能,无需修改现有代码。
依赖倒置原则
处理者之间通过接口通信,不直接依赖具体实现。
八、实际开发中的注意事项
避免链过长
链过长可能导致性能问题,需合理设计处理者的数量。
确保有终止节点
防止请求无限传递,例如在最后一个处理者中明确终止逻辑。
动态调整链的结构
在运行时动态添加或移除处理者,增强灵活性。
日志和调试
在处理者中添加日志,便于追踪请求的处理路径。
九、总结
责任链模式通过链式结构实现请求的灵活处理,其核心思想是让请求自己寻找合适的处理者。在 Web 开发中,过滤器链是责任链模式的典型应用,通过链式结构实现请求的预处理和后处理。无论是审批流程、事件处理,还是 Web 过滤器链,责任链模式都能提供解耦、灵活、可扩展的解决方案。
评论区