前言

在软件开发中,我们经常遇到需要多个对象处理同一请求的场景。比如请假审批流程需要不同级别的领导审批、日志系统需要根据日志级别决定输出方式、Web请求需要经过一系列过滤器的处理…这些场景都有一个共同特点:请求需要经过一系列处理步骤,每个步骤可能处理请求,也可能将其传递给下一个步骤

责任链模式(Chain of Responsibility Pattern)正是为这类问题提供了优雅的解决方案。本文将深入浅出地介绍责任链模式,并通过Java示例和Spring Boot实战,帮助你掌握这一强大工具。

1. 责任链模式概述

1.1 什么是责任链模式?

责任链模式是一种行为型设计模式,它创建了一个对象链,每个对象都有机会处理请求。请求沿着这条链传递,直到有一个对象处理它为止,或者直到链的末端。

这种模式的核心思想是:解耦请求的发送者和接收者,让多个接收者都有机会处理请求,而发送者不需要知道具体哪个接收者处理了请求。

1.2 生活中的类比

想象一下你为电脑新买了一个硬件设备,但Linux系统不支持它。你拨打技术支持电话:

  • 首先听到自动回复器,提供常见解决方案,但你的问题不在其中
  • 自动回复器将你转接到人工接听人员,他翻阅手册但仍无法解决
  • 接听人员将你转给真正的工程师,他终于告诉了你正确的驱动程序下载地址

这就是一个典型的责任链——你的问题(请求)沿着支持人员(处理者)组成的链传递,直到找到能解决它的人。

2. 责任链模式的结构

2.1 核心角色

责任链模式主要包含以下几个角色:

角色 职责
抽象处理者(Handler) 定义处理请求的接口,包含指向下一个处理者的引用
具体处理者(ConcreteHandler) 实现处理逻辑,如果能处理则处理,否则传递给下一个
客户端(Client) 创建处理者对象并构建责任链,向链发送请求

2.2 类图结构

┌─────────────┐       ┌─────────────────┐
│   Client    │──────▶│    Handler      │
└─────────────┘       │─────────────────│
                      │+next: Handler   │
                      │+setNext()       │
                      │+handleRequest() │
                      └────────┬────────┘
                               ▲
                  ┌────────────┴────────────┐
                  │                         │
        ┌─────────┴─────────┐     ┌─────────┴─────────┐
        │ ConcreteHandler1  │     │ ConcreteHandler2  │
        │───────────────────│     │───────────────────│
        │+handleRequest()   │     │+handleRequest()   │
        └───────────────────┘     └───────────────────┘

3. Java示例:请假审批系统

让我们通过一个实际的请假审批案例来理解责任链模式的实现。规则如下:

  • 请假 1-3 天:部门主管审批
  • 请假 4-7 天:部门经理审批
  • 请假 8-30 天:总经理审批
  • 请假超过 30 天:不予批准

3.1 创建请求类

// 请假请求类
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.2 创建抽象处理者

// 抽象审批者
public abstract class Approver {
    // 下一个审批者
    protected Approver nextApprover;
    
    // 设置下一个审批者
    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }
    
    // 处理请假请求的抽象方法
    public abstract void processRequest(LeaveRequest request);
}

3.3 创建具体处理者

// 部门主管
public class Director extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        // 处理1-3天的请假
        if (request.getLeaveDays() >= 1 && request.getLeaveDays() <= 3) {
            System.out.println("部门主管批准 " + request.getEmployeeName() + 
                             " 请假 " + request.getLeaveDays() + " 天");
        } 
        // 超过3天则交给下一个审批者
        else if (nextApprover != null) {
            nextApprover.processRequest(request);
        }
    }
}

// 部门经理
public class Manager extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        // 处理4-7天的请假
        if (request.getLeaveDays() >= 4 && request.getLeaveDays() <= 7) {
            System.out.println("部门经理批准 " + request.getEmployeeName() + 
                             " 请假 " + request.getLeaveDays() + " 天");
        } 
        // 超过7天则交给下一个审批者
        else if (nextApprover != null) {
            nextApprover.processRequest(request);
        }
    }
}

// 总经理
public class GeneralManager extends Approver {
    @Override
    public void processRequest(LeaveRequest request) {
        // 处理8-30天的请假
        if (request.getLeaveDays() >= 8 && request.getLeaveDays() <= 30) {
            System.out.println("总经理批准 " + request.getEmployeeName() + 
                             " 请假 " + request.getLeaveDays() + " 天");
        } 
        // 超过30天则不予批准
        else {
            System.out.println(request.getEmployeeName() + " 请假 " + 
                             request.getLeaveDays() + " 天,超过最大允许天数,不予批准");
        }
    }
}

3.4 客户端使用

public class Client {
    public static void main(String[] args) {
        // 创建各个审批者
        Approver director = new Director();
        Approver manager = new Manager();
        Approver generalManager = new GeneralManager();
        
        // 构建责任链:部门主管 -> 部门经理 -> 总经理
        director.setNextApprover(manager);
        manager.setNextApprover(generalManager);
        
        // 创建不同的请假请求
        LeaveRequest request1 = new LeaveRequest("张三", 2);
        LeaveRequest request2 = new LeaveRequest("李四", 5);
        LeaveRequest request3 = new LeaveRequest("王五", 15);
        LeaveRequest request4 = new LeaveRequest("赵六", 35);
        
        // 处理请求
        director.processRequest(request1);
        director.processRequest(request2);
        director.processRequest(request3);
        director.processRequest(request4);
    }
}

运行结果:

部门主管批准 张三 请假 2 天
部门经理批准 李四 请假 5 天
总经理批准 王五 请假 15 天
赵六 请假 35 天,超过最大允许天数,不予批准

4. Spring Boot中的责任链模式应用

在Spring Boot项目中,责任链模式可以帮助我们实现复杂接口的解耦和动态编排。下面以订单处理系统为例,展示如何在Spring Boot中优雅地实现责任链模式。

4.1 场景描述

假设我们有一个订单处理系统,订单需要经过多个环节的处理:

  1. 验证订单:检查订单是否有效
  2. 计算金额:计算订单总金额(含税等)
  3. 检查库存:确认商品库存充足
  4. 处理支付:执行支付操作

4.2 定义处理器接口

public interface OrderHandler {
    /**
     * 处理订单
     * @param order 订单对象
     */
    void handle(Order order);
    
    /**
     * 设置下一个处理器
     * @param nextHandler 下一个处理器
     */
    void setNextHandler(OrderHandler nextHandler);
}

4.3 创建订单类

public class Order {
    private Long id;
    private double amount;           // 订单金额
    private boolean valid;            // 是否有效
    private String productId;         // 商品ID
    private int stock;                // 库存数量
    private boolean paymentSuccess;   // 支付是否成功
    
    // 构造方法、getter和setter
    public Order(Long id, double amount, boolean valid, String productId, int stock) {
        this.id = id;
        this.amount = amount;
        this.valid = valid;
        this.productId = productId;
        this.stock = stock;
    }
    
    // getter和setter方法
    public Long getId() { return id; }
    public double getAmount() { return amount; }
    public void setAmount(double amount) { this.amount = amount; }
    public boolean isValid() { return valid; }
    public void setValid(boolean valid) { this.valid = valid; }
    public String getProductId() { return productId; }
    public int getStock() { return stock; }
    public void setStock(int stock) { this.stock = stock; }
    public boolean isPaymentSuccess() { return paymentSuccess; }
    public void setPaymentSuccess(boolean paymentSuccess) { this.paymentSuccess = paymentSuccess; }
}

4.4 实现具体处理器(使用Spring注解)

@Component
public class OrderValidationHandler implements OrderHandler {
    private OrderHandler nextHandler;
    
    @Override
    public void handle(Order order) {
        System.out.println("【1.验证订单】验证订单有效性...");
        // 执行订单验证逻辑
        if (order.isValid()) {
            System.out.println("    订单验证通过");
            if (nextHandler != null) {
                nextHandler.handle(order);
            }
        } else {
            System.out.println("    订单验证失败,终止处理");
        }
    }
    
    @Override
    public void setNextHandler(OrderHandler nextHandler) {
        this.nextHandler = nextHandler;
    }
}

@Component
public class OrderCalculationHandler implements OrderHandler {
    private OrderHandler nextHandler;
    
    @Override
    public void handle(Order order) {
        System.out.println("【2.计算金额】计算订单金额...");
        // 执行订单金额计算逻辑(加上10%的税)
        double originalAmount = order.getAmount();
        double finalAmount = originalAmount * 1.1;
        order.setAmount(finalAmount);
        System.out.println("    原金额:" + originalAmount + ",税后金额:" + finalAmount);
        
        if (nextHandler != null) {
            nextHandler.handle(order);
        }
    }
    
    @Override
    public void setNextHandler(OrderHandler nextHandler) {
        this.nextHandler = nextHandler;
    }
}

@Component
public class OrderStockHandler implements OrderHandler {
    private OrderHandler nextHandler;
    
    @Override
    public void handle(Order order) {
        System.out.println("【3.检查库存】检查商品库存...");
        // 模拟库存检查(假设需要5件库存)
        int requiredStock = 5;
        if (order.getStock() >= requiredStock) {
            System.out.println("    库存充足,扣除库存");
            order.setStock(order.getStock() - requiredStock);
            if (nextHandler != null) {
                nextHandler.handle(order);
            }
        } else {
            System.out.println("    库存不足,终止处理");
        }
    }
    
    @Override
    public void setNextHandler(OrderHandler nextHandler) {
        this.nextHandler = nextHandler;
    }
}

@Component
public class OrderPaymentHandler implements OrderHandler {
    private OrderHandler nextHandler;
    
    @Override
    public void handle(Order order) {
        System.out.println("【4.处理支付】执行支付操作...");
        // 执行支付逻辑
        if (order.getAmount() > 0) {
            System.out.println("    支付成功!订单金额:" + order.getAmount());
            order.setPaymentSuccess(true);
            // 这是最后一个处理器,不再传递
        } else {
            System.out.println("    支付失败:金额无效");
            order.setPaymentSuccess(false);
        }
    }
    
    @Override
    public void setNextHandler(OrderHandler nextHandler) {
        this.nextHandler = nextHandler;
    }
}

4.5 配置责任链(Spring配置类)

@Configuration
public class OrderChainConfig {
    
    @Autowired
    private OrderValidationHandler validationHandler;
    
    @Autowired
    private OrderCalculationHandler calculationHandler;
    
    @Autowired
    private OrderStockHandler stockHandler;
    
    @Autowired
    private OrderPaymentHandler paymentHandler;
    
    /**
     * 组装责任链:验证 -> 计算 -> 库存 -> 支付
     */
    @Bean
    public OrderHandler orderHandlerChain() {
        validationHandler.setNextHandler(calculationHandler);
        calculationHandler.setNextHandler(stockHandler);
        stockHandler.setNextHandler(paymentHandler);
        // 支付处理器是最后一个,不需要设置下一个
        
        return validationHandler; // 返回链的第一个处理器
    }
}

4.6 创建订单服务

@Service
public class OrderService {
    
    @Autowired
    private OrderHandler orderHandlerChain;
    
    /**
     * 处理订单
     */
    public void processOrder(Order order) {
        System.out.println("========== 开始处理订单 ==========");
        orderHandlerChain.handle(order);
        System.out.println("========== 订单处理完成 ==========");
        System.out.println("最终订单状态:" + 
            (order.isPaymentSuccess() ? "支付成功" : "处理失败"));
    }
}

4.7 控制器层调用

@RestController
@RequestMapping("/api/orders")
public class OrderController {
    
    @Autowired
    private OrderService orderService;
    
    @GetMapping("/process/{id}")
    public String processOrder(@PathVariable Long id) {
        // 模拟创建订单
        Order order = new Order(id, 100.0, true, "PROD-001", 10);
        
        // 处理订单
        orderService.processOrder(order);
        
        return "订单处理完成,支付状态:" + order.isPaymentSuccess();
    }
}

4.8 运行结果

启动Spring Boot应用,访问 /api/orders/process/123,控制台输出:

========== 开始处理订单 ==========
【1.验证订单】验证订单有效性...
    订单验证通过
【2.计算金额】计算订单金额...
    原金额:100.0,税后金额:110.0
【3.检查库存】检查商品库存...
    库存充足,扣除库存
【4.处理支付】执行支付操作...
    支付成功!订单金额:110.0
========== 订单处理完成 ==========
最终订单状态:支付成功

5. 责任链模式的变种

除了标准的线性责任链,还有其他几种常见形式:

5.1 Pipeline-Valve模型(Tomcat风格)

这种模型的特点是有一个基础的Valve(BaseValve)始终在链的最后执行,且不可删除:

public interface Valve {
    Valve getNextValve();
    void setNextValve(Valve next);
    void invoke(ValveContext context);
}

public interface Pipeline {
    void setBasic(Valve valve);  // 设置基础Valve
    void addValve(Valve valve);  // 添加普通Valve
    void process(ValveContext context);  // 启动处理
}

5.2 其他变种

  • 环形责任链:最后一个处理者指向第一个处理者
  • 树形责任链:一个处理者可以有多个后继者
  • 带条件的责任链:根据条件动态决定下一个处理者

6. 责任链模式的优缺点

6.1 优点

优点 说明
降低耦合度 请求的发送者和接收者解耦,发送者无需知道谁处理了请求
灵活性高 可以灵活地改变链的结构和处理顺序
符合开闭原则 新增处理者不需要修改原有代码
单一职责原则 每个处理者只需关注自己的职责范围
控制处理顺序 可以精确控制请求处理的顺序

6.2 缺点

缺点 说明
请求可能不被处理 如果链中没有对象能处理请求,请求可能会被丢弃
调试复杂 请求的处理路径可能较长,调试时需要跟踪整个链
性能影响 对于长链,循环调用可能带来一定的性能开销
可能形成循环 如果不慎形成环形链,可能导致死循环

7. 使用场景总结

责任链模式适用于以下场景:

7.1 常见应用场景

场景类别 具体示例
审批流程 请假审批、报销审批、采购审批等多级审批
日志系统 不同级别(DEBUG/INFO/ERROR)的日志由不同处理器处理
Web过滤器 Servlet Filter、Spring Interceptor 组成的过滤器链
权限验证 登录认证、权限检查、角色验证等依次执行
异常处理 多层异常捕获处理机制
事件冒泡 GUI中的事件传递机制(如JavaScript事件冒泡)
订单处理 电商订单的验证、计算、库存、支付等环节

7.2 Java标准库中的责任链模式

责任链模式在Java核心库和主流框架中有着广泛应用:

  • Servlet Filter:所有Filter组成一个链,依次处理请求
  • Spring Interceptor:拦截器链对请求进行预处理和后处理
  • Spring Security:过滤器链处理认证和授权
  • Netty ChannelPipeline:处理网络事件的责任链
  • Java异常处理:try-catch块的嵌套本质上也是一种责任链
  • Java日志框架:java.util.logging.Logger会将日志记录请求传递给父处理器

8. 最佳实践建议

在使用责任链模式时,以下几点值得注意:

  1. 避免过长的责任链:过长的链会影响性能,考虑使用异步或限制链长度
  2. 确保请求能被处理:可以在链的末尾添加一个兜底处理器,处理未被处理的请求
  3. 合理划分职责:每个处理者应该职责单一,避免处理逻辑过于复杂
  4. 考虑线程安全:如果责任链被多个线程共享,需要考虑处理器的线程安全性
  5. 支持动态编排:结合Spring容器,可以在运行时动态调整处理链的顺序
  6. 记录处理链路:添加日志或追踪ID,便于调试和监控

总结

责任链模式通过构建处理者对象链,让请求在链中传递直至被处理,有效解耦了请求发送者和接收者。它特别适合处理那些需要多级处理或动态调整处理流程的场景。

在Spring Boot项目中,结合依赖注入和配置类,我们可以非常优雅地实现责任链模式,实现业务逻辑的解耦和动态编排。无论是请假审批、订单处理还是权限验证,责任链模式都能让你的代码更加灵活、可扩展,更好地应对复杂业务场景的变化。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐