Skip to content

责任链模式(Chain of Responsibility Pattern)

概述

责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。

核心思想

  • 将多个对象连成一条链,并沿着这条链传递请求,直到有对象处理它为止
  • 发出请求的对象不需要知道链的结构,也不需要知道哪个对象会处理请求
  • 降低了对象之间的耦合度

适用场景

  1. 多个对象可以处理同一请求,但具体由哪个对象处理在运行时动态决定
  2. 需要动态指定处理请求的对象集合
  3. 不想让客户端知道具体的处理者
  4. 需要按顺序执行多个处理器

常见应用场景

  • 审批流程:请假审批、报销审批(组长 → 经理 → 总监 → CEO)
  • 日志处理:不同级别的日志由不同的处理器处理
  • 异常处理:异常沿着调用栈向上传递
  • 过滤器链:Servlet Filter、Spring Interceptor
  • 权限校验:多级权限验证
  • 数据验证:多个验证规则依次执行

UML 类图

┌─────────────────┐
│    Handler      │ (抽象处理者)
├─────────────────┤
│ - next: Handler │
├─────────────────┤
│ + setNext()     │
│ + handleRequest()│
└─────────────────┘


        ├──────────────────┬──────────────────┐
        │                  │                  │
┌───────────────┐  ┌───────────────┐  ┌───────────────┐
│ConcreteHandler1│  │ConcreteHandler2│  │ConcreteHandler3│
├───────────────┤  ├───────────────┤  ├───────────────┤
│+ handleRequest()│  │+ handleRequest()│  │+ handleRequest()│
└───────────────┘  └───────────────┘  └───────────────┘

角色组成

  1. 抽象处理者(Handler)

    • 定义处理请求的接口
    • 维护下一个处理者的引用
  2. 具体处理者(ConcreteHandler)

    • 实现处理请求的方法
    • 判断是否能处理请求,不能则传递给下一个处理者
  3. 客户端(Client)

    • 创建处理链
    • 向链的第一个处理者提交请求

实现方式

方式一:传统实现(链式传递)

每个处理者持有下一个处理者的引用,如果自己不能处理则传递给下一个。

示例:请假审批流程

java
// 抽象处理者
public abstract class Approver {
    protected Approver nextApprover;
    protected String name;

    public Approver(String name) {
        this.name = name;
    }

    // 设置下一个处理者
    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    // 处理请求
    public abstract void processRequest(LeaveRequest request);
}

// 请假请求
public class LeaveRequest {
    private String name;
    private int days;

    public LeaveRequest(String name, int days) {
        this.name = name;
        this.days = days;
    }

    public String getName() { return name; }
    public int getDays() { return days; }
}

// 具体处理者:组长(处理 1 天以内的请假)
public class TeamLeader extends Approver {
    public TeamLeader(String name) {
        super(name);
    }

    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 1) {
            System.out.println("组长 " + name + " 批准了 " + request.getName() + " 的 " + request.getDays() + " 天请假");
        } else {
            System.out.println("组长 " + name + " 无权批准,转交上级");
            if (nextApprover != null) {
                nextApprover.processRequest(request);
            }
        }
    }
}

// 具体处理者:经理(处理 3 天以内的请假)
public class Manager extends Approver {
    public Manager(String name) {
        super(name);
    }

    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 3) {
            System.out.println("经理 " + name + " 批准了 " + request.getName() + " 的 " + request.getDays() + " 天请假");
        } else {
            System.out.println("经理 " + name + " 无权批准,转交上级");
            if (nextApprover != null) {
                nextApprover.processRequest(request);
            }
        }
    }
}

// 具体处理者:总监(处理 7 天以内的请假)
public class Director extends Approver {
    public Director(String name) {
        super(name);
    }

    @Override
    public void processRequest(LeaveRequest request) {
        if (request.getDays() <= 7) {
            System.out.println("总监 " + name + " 批准了 " + request.getName() + " 的 " + request.getDays() + " 天请假");
        } else {
            System.out.println("总监 " + name + " 无权批准,转交上级");
            if (nextApprover != null) {
                nextApprover.processRequest(request);
            }
        }
    }
}

// 客户端测试
public class Client {
    public static void main(String[] args) {
        // 创建处理者
        Approver teamLeader = new TeamLeader("张三");
        Approver manager = new Manager("李四");
        Approver director = new Director("王五");

        // 构建责任链
        teamLeader.setNextApprover(manager);
        manager.setNextApprover(director);

        // 提交请求
        LeaveRequest request1 = new LeaveRequest("小明", 1);
        teamLeader.processRequest(request1);
        // 输出: 组长 张三 批准了 小明 的 1 天请假

        System.out.println("---");

        LeaveRequest request2 = new LeaveRequest("小红", 3);
        teamLeader.processRequest(request2);
        // 输出: 组长 张三 无权批准,转交上级
        //      经理 李四 批准了 小红 的 3 天请假

        System.out.println("---");

        LeaveRequest request3 = new LeaveRequest("小刚", 7);
        teamLeader.processRequest(request3);
        // 输出: 组长 张三 无权批准,转交上级
        //      经理 李四 无权批准,转交上级
        //      总监 王五 批准了 小刚 的 7 天请假
    }
}

方式二:集合实现(统一管理)

使用 List 统一管理所有处理者,由链管理器负责调用。

java
// 抽象处理者
public interface Handler {
    boolean handle(Request request);
}

// 请求对象
public class Request {
    private String type;
    private String content;

    public Request(String type, String content) {
        this.type = type;
        this.content = content;
    }

    public String getType() { return type; }
    public String getContent() { return content; }
}

// 具体处理者:日志处理器
public class LogHandler implements Handler {
    @Override
    public boolean handle(Request request) {
        if ("LOG".equals(request.getType())) {
            System.out.println("LogHandler 处理日志: " + request.getContent());
            return true;
        }
        return false;
    }
}

// 具体处理者:异常处理器
public class ExceptionHandler implements Handler {
    @Override
    public boolean handle(Request request) {
        if ("EXCEPTION".equals(request.getType())) {
            System.out.println("ExceptionHandler 处理异常: " + request.getContent());
            return true;
        }
        return false;
    }
}

// 责任链管理器
public class HandlerChain {
    private List<Handler> handlers = new ArrayList<>();

    public void addHandler(Handler handler) {
        handlers.add(handler);
    }

    public void process(Request request) {
        for (Handler handler : handlers) {
            if (handler.handle(request)) {
                System.out.println("请求已被处理");
                return;
            }
        }
        System.out.println("没有处理者能处理该请求");
    }
}

// 客户端测试
public class Client {
    public static void main(String[] args) {
        HandlerChain chain = new HandlerChain();
        chain.addHandler(new LogHandler());
        chain.addHandler(new ExceptionHandler());

        Request request1 = new Request("LOG", "系统启动");
        chain.process(request1);
        // 输出: LogHandler 处理日志: 系统启动
        //      请求已被处理

        Request request2 = new Request("EXCEPTION", "空指针异常");
        chain.process(request2);
        // 输出: ExceptionHandler 处理异常: 空指针异常
        //      请求已被处理
    }
}

方式三:Spring 实现(依赖注入)

利用 Spring 的依赖注入和 @Order 注解管理责任链。

java
// 抽象处理者
public interface ValidationHandler {
    boolean validate(User user);
    int getOrder();
}

// 用户对象
@Data
public class User {
    private String username;
    private String password;
    private Integer age;
}

// 具体处理者:用户名验证
@Component
@Order(1)
public class UsernameValidationHandler implements ValidationHandler {
    @Override
    public boolean validate(User user) {
        if (user.getUsername() == null || user.getUsername().isEmpty()) {
            System.out.println("用户名不能为空");
            return false;
        }
        System.out.println("用户名验证通过");
        return true;
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

// 具体处理者:密码验证
@Component
@Order(2)
public class PasswordValidationHandler implements ValidationHandler {
    @Override
    public boolean validate(User user) {
        if (user.getPassword() == null || user.getPassword().length() < 6) {
            System.out.println("密码长度不能少于6位");
            return false;
        }
        System.out.println("密码验证通过");
        return true;
    }

    @Override
    public int getOrder() {
        return 2;
    }
}

// 具体处理者:年龄验证
@Component
@Order(3)
public class AgeValidationHandler implements ValidationHandler {
    @Override
    public boolean validate(User user) {
        if (user.getAge() == null || user.getAge() < 18) {
            System.out.println("年龄必须大于18岁");
            return false;
        }
        System.out.println("年龄验证通过");
        return true;
    }

    @Override
    public int getOrder() {
        return 3;
    }
}

// 验证服务
@Service
@RequiredArgsConstructor
public class UserValidationService {
    private final List<ValidationHandler> handlers;

    public boolean validateUser(User user) {
        // Spring 会自动按 @Order 排序注入
        for (ValidationHandler handler : handlers) {
            if (!handler.validate(user)) {
                return false;
            }
        }
        return true;
    }
}

// 控制器
@RestController
@RequiredArgsConstructor
public class UserController {
    private final UserValidationService validationService;

    @PostMapping("/register")
    public String register(@RequestBody User user) {
        if (validationService.validateUser(user)) {
            return "注册成功";
        }
        return "注册失败";
    }
}

实际应用场景

1. Servlet Filter 过滤器链

java
public class AuthenticationFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 认证逻辑
        System.out.println("执行认证过滤器");

        // 传递给下一个过滤器
        chain.doFilter(request, response);
    }
}

public class LoggingFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 日志记录
        System.out.println("执行日志过滤器");

        // 传递给下一个过滤器
        chain.doFilter(request, response);
    }
}

2. Spring Interceptor 拦截器链

java
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 登录检查
        String token = request.getHeader("token");
        if (token == null) {
            response.setStatus(401);
            return false; // 中断链
        }
        return true; // 继续执行
    }
}

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/login", "/register");
    }
}

3. MyBatis 插件拦截器链

java
@Intercepts({
    @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class SqlLogInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("执行 SQL 日志拦截器");
        return invocation.proceed(); // 继续执行
    }
}

优点

  1. 降低耦合度

    • 请求发送者和接收者解耦
    • 发送者不需要知道具体哪个对象会处理请求
  2. 增强灵活性

    • 可以动态添加或删除处理者
    • 可以改变处理者的顺序
  3. 符合单一职责原则

    • 每个处理者只负责自己的处理逻辑
  4. 符合开闭原则

    • 新增处理者不需要修改现有代码

缺点

  1. 性能问题

    • 请求可能需要遍历整个链才能被处理
    • 链过长会影响性能
  2. 调试困难

    • 请求的处理路径不明确
    • 难以追踪请求在哪个环节被处理
  3. 不保证请求被处理

    • 如果链配置不当,请求可能到达链尾仍未被处理
    • 需要有兜底处理机制
  4. 可能产生循环调用

    • 如果链配置错误,可能导致死循环

使用注意事项

  1. 避免链过长

    • 控制处理者数量,避免性能问题
    • 考虑使用其他设计模式(如策略模式)
  2. 确保请求被处理

    • 在链尾添加默认处理者
    • 或者抛出异常提示未处理
  3. 明确处理者职责

    • 每个处理者只处理特定类型的请求
    • 避免职责重叠
  4. 考虑线程安全

    • 如果处理者有状态,需要考虑并发问题
    • 建议使用无状态的处理者

与其他模式的对比

责任链模式 vs 策略模式

对比项责任链模式策略模式
处理方式多个处理者依次处理选择一个策略处理
处理者数量可以有多个处理者参与只有一个策略执行
选择时机运行时动态选择通常在创建时选择
适用场景多级审批、过滤器链算法替换、支付方式

责任链模式 vs 装饰器模式

对比项责任链模式装饰器模式
目的处理请求增强功能
中断性可以中断链不能中断
顺序顺序重要顺序可能不重要
返回值可能不返回通常有返回值

总结

责任链模式是一种非常实用的行为设计模式,特别适合以下场景:

  1. 多级审批流程:请假审批、报销审批、采购审批
  2. 过滤器链:Web 过滤器、拦截器、插件系统
  3. 数据验证:多个验证规则依次执行
  4. 日志处理:不同级别的日志由不同处理器处理
  5. 异常处理:异常沿着调用栈向上传递

关键要点

  • 解耦请求发送者和接收者:发送者不需要知道谁会处理请求
  • 动态组合处理者:可以灵活地添加、删除、重排处理者
  • 单一职责:每个处理者只负责自己的处理逻辑
  • 注意性能:避免链过长,确保请求能被处理

实现建议

  1. 传统链式实现:适合处理者固定、顺序明确的场景
  2. 集合管理实现:适合处理者动态变化的场景
  3. Spring 依赖注入:适合企业级应用,利用框架特性

责任链模式在 Java Web 开发中应用广泛,掌握这个模式对理解 Servlet Filter、Spring Interceptor 等框架机制非常有帮助。

Released under the MIT License.