大家好,欢迎来到设计模式系列文章(基础篇)的第三十四篇内容。在上一篇中,我们学习了行为型模式的第二十三种常用模式——命令模式,其核心是将请求封装成独立的命令对象,实现请求发送者与接收者的完全解耦,同时支持请求的排队、撤销、重做等灵活操作,广泛应用于遥控器控制、订单系统等场景。今天,我们将学习行为型模式的第二十四种常用模式——责任链模式,它的核心是将多个处理请求的对象连成一条链,当请求发出时,沿着这条链依次传递,直到有一个对象能够处理该请求为止,实现请求的分发与处理解耦,支持动态调整处理流程,大幅提升系统的灵活性和可扩展性。
在日常开发和生活中,责任链模式的应用十分普遍。比如公司的请假审批流程:员工请假1天以内,部门主管即可审批;1-3天需要经理审批;3天以上需要总经理审批,员工提交请假申请后,申请会沿着“部门主管→经理→总经理”这条链传递,直到有对应的审批人处理该申请;再比如电商系统的订单退款审核流程:退款金额100元以内,系统自动审核通过;100-1000元需要客服审核;1000元以上需要财务审核,退款请求会沿着“系统自动审核→客服审核→财务审核”的链条传递,找到对应的处理者;还有前端的拦截器链、后端的过滤器链,请求会依次经过每个拦截器/过滤器处理,直到完成所有处理或被拦截。
如果我们不使用责任链模式,会将所有请求处理逻辑集中在一个类中,通过大量的if-else或switch-case判断请求类型,找到对应的处理者,这样会导致代码臃肿、耦合度高,新增或修改处理逻辑时,需要修改原有代码,违背开闭原则。同时,无法动态调整处理流程,处理者之间的依赖关系紧密,难以维护。责任链模式则通过将每个处理者封装成独立的对象,连成一条链,请求沿着链条传递,处理者只负责自己能处理的请求,无法处理则传递给下一个处理者,实现了请求与处理者的解耦,同时支持动态添加、删除处理者,调整链条顺序,让系统变得更加灵活、可扩展。今天,我们就从核心定义、结构、实战实现、场景对比、避坑指南全维度讲解,帮大家彻底掌握这种“请求链式处理”的实用设计模式。

一、责任链模式的核心定义与设计初衷

1. 核心定义
责任链模式(Chain of Responsibility Pattern):为请求创建一个接收者对象的链,使多个接收者都有机会处理请求,将请求的发送者与接收者解耦,请求沿着链传递,直到有一个接收者处理它为止。核心是链式组织处理者、请求分发处理、解耦发送者与接收者。
通俗理解:责任链模式就像我们去医院看病,需要依次经过“挂号→问诊→检查→取药”四个环节,每个环节的医护人员(处理者)只负责自己的工作:挂号员负责挂号,无法处理问诊;问诊医生负责问诊,无法处理检查;检查医生负责检查,无法处理取药;取药员负责取药,完成整个流程。患者(请求发送者)只需提交看病请求,请求会沿着“挂号员→问诊医生→检查医生→取药员”这条链传递,直到所有环节处理完成,患者无需知道每个环节的具体处理者,也无需关心处理顺序,实现了请求与处理者的解耦。

2. 设计初衷(解决的核心问题)
责任链模式的出现,核心是解决“请求处理者过多、处理逻辑分散,请求发送者与处理者耦合过高,无法动态调整处理流程”的痛点,具体解决4个核心问题:

  • 解耦请求发送者与处理者:发送者无需知道具体的处理者是谁,也无需知道处理顺序,只需将请求提交给责任链,由链条自行分发处理;
  • 实现请求的分发处理:每个处理者只负责处理自己能处理的请求,无法处理则传递给下一个处理者,避免处理逻辑混乱;
  • 支持动态调整处理流程:可动态添加、删除处理者,调整处理者的顺序,无需修改原有代码,灵活性极强;
  • 提升系统扩展性:新增处理逻辑时,只需新增对应的处理者类,加入责任链即可,符合开闭原则,降低系统维护成本。

3. 设计原则适配
责任链模式严格贴合面向对象设计核心原则,是实现请求链式处理与解耦的最佳实践,具体适配如下:

  • 开闭原则:新增处理者时,只需新增处理者类,加入责任链即可,无需修改原有处理者和发送者代码,扩展性强;
  • 单一职责原则:每个处理者只负责处理一种或一类请求,职责单一,避免处理逻辑混乱;
  • 依赖倒转原则:处理者依赖抽象处理者接口,不依赖具体处理者;发送者依赖抽象处理者接口,不依赖具体处理者,便于替换和扩展;
  • 迪米特法则(最少知道原则):发送者只需知道责任链的入口,无需知道链条中的具体处理者和处理顺序;处理者只需知道下一个处理者,无需知道整个链条的结构,降低耦合度。

二、责任链模式的核心结构(3个核心角色)

责任链模式的结构围绕“链式组织处理者、请求分发处理”展开,核心包含3个角色,各司其职、协同完成请求的链式传递与处理,我们以“电商订单退款审核流程”为场景,逐一拆解角色职责与交互逻辑:

1. 抽象处理者(Handler)
所有具体处理者的抽象父类或接口,定义了处理请求的核心方法(如处理请求、设置下一个处理者),规范了所有具体处理者必须实现的行为。抽象处理者还持有一个下一个处理者的引用,用于将无法处理的请求传递给下一个处理者,构成责任链。对应电商退款审核场景中的“抽象审核者”,定义审核请求和设置下一个审核者的接口。

2. 具体处理者(Concrete Handler)
实现抽象处理者接口,封装了具体的请求处理逻辑,负责判断当前请求是否属于自己的处理范围:若能处理,则执行处理逻辑;若不能处理,则将请求传递给下一个处理者。每个具体处理者对应一种或一类请求的处理逻辑,是责任链的核心实现类。对应电商退款审核场景中的“系统自动审核者”“客服审核者”“财务审核者”,分别处理不同金额的退款请求。

3. 请求者(Client)
发起请求的对象,负责创建请求对象,将请求提交给责任链的入口处理者,无需关心请求的具体处理过程和处理者,只需等待处理结果。对应电商退款审核场景中的“用户”,提交退款请求,无需关心审核流程和审核者,只需等待审核结果。
核心关系总结:抽象处理者定义处理规范并持有下一个处理者的引用;具体处理者实现处理逻辑,判断并处理请求,无法处理则传递给下一个处理者;请求者发起请求,提交给责任链入口,请求沿着链条传递,直到被处理或链条结束。处理者之间通过“下一个处理者”引用构成链条,可动态调整链条结构。

三、责任链模式的核心逻辑与执行流程

责任链模式的核心逻辑是“链式组织处理者、请求分发处理,解耦发送与执行”,标准执行流程分为七步,全程实现请求与处理者的解耦,支持动态调整链条,我们以“电商订单退款审核流程”为例,拆解执行流程:

  1. 定义抽象处理者接口:声明处理请求的方法和设置下一个处理者的方法,规范具体处理者的实现;
  2. 实现具体处理者类:每个具体处理者类实现抽象处理者接口,封装具体的处理逻辑,判断请求是否可处理,可处理则执行,不可处理则传递给下一个处理者;
  3. 创建请求对象:请求者创建请求对象,包含请求的核心信息(如退款金额、订单号);
  4. 构建责任链:将具体处理者对象按处理顺序连接起来,设置每个处理者的下一个处理者,形成责任链;
  5. 请求者提交请求:请求者将请求提交给责任链的入口处理者;
  6. 请求链式传递与处理:入口处理者判断请求是否可处理,可处理则执行处理逻辑,不可处理则传递给下一个处理者,依次类推,直到请求被处理或链条结束;
  7. 返回处理结果:处理完成后,将处理结果返回给请求者;若链条中无处理者能处理请求,返回处理失败提示。
    关键要点:责任链的核心是“传递”,处理者只负责自己能处理的请求,不关心其他处理者的实现;请求者无需知道链条结构,只需提交请求;链条可动态调整,新增、删除、调整处理者顺序,无需修改请求者和原有处理者代码;每个处理者只与下一个处理者交互,降低了处理者之间的耦合度。

四、责任链模式的实战实现(电商订单退款审核场景)

我们以高频的电商订单退款审核流程为场景,使用Java代码实现责任链模式,退款审核链包含三个处理者:系统自动审核(处理100元以内退款)、客服审核(处理100-1000元退款)、财务审核(处理1000元以上退款),用户提交退款请求后,请求沿着链条传递,直到被对应处理者审核,直观体现责任链模式“请求链式处理、解耦发送与执行”的核心优势。
场景说明:用户提交退款请求,包含订单号和退款金额;系统自动审核处理100元(含)以内的退款,无需人工干预,直接审核通过;客服审核处理100-1000元(含)的退款,人工审核后通过;财务审核处理1000元以上的退款,财务审核后通过;若退款金额为负数或0,直接返回审核失败;请求沿着“系统自动审核→客服审核→财务审核”的链条传递,直到被处理。

1. 第一步:定义请求对象(RefundRequest)

// 请求对象:退款请求,包含请求核心信息
public class RefundRequest {
    // 订单号
    private String orderNo;
    // 退款金额
    private double amount;

    // 构造方法
    public RefundRequest(String orderNo, double amount) {
        this.orderNo = orderNo;
        this.amount = amount;
    }

    // getter/setter方法
    public String getOrderNo() {
        return orderNo;
    }

    public double getAmount() {
        return amount;
    }
}

2. 第二步:定义抽象处理者接口(Handler)

// 抽象处理者:抽象退款审核者,定义审核方法和设置下一个处理者的方法
public interface RefundHandler {
    // 设置下一个处理者
    void setNextHandler(RefundHandler nextHandler);

    // 处理退款请求
    String handleRefund(RefundRequest request);
}

3. 第三步:实现具体处理者类(Concrete Handler)

(1)系统自动审核者(处理100元以内退款)

// 具体处理者:系统自动审核者,处理100元(含)以内的退款
public class SystemAutoHandler implements RefundHandler {
    // 下一个处理者
    private RefundHandler nextHandler;

    // 设置下一个处理者
    @Override
    public void setNextHandler(RefundHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    // 处理退款请求
    @Override
    public String handleRefund(RefundRequest request) {
        double amount = request.getAmount();
        String orderNo = request.getOrderNo();

        // 先判断退款金额是否有效
        if (amount <= 0) {
            return String.format("订单号:%s,退款金额无效(%.2f元),审核失败", orderNo, amount);
        }

        // 处理100元以内的退款
        if (amount <= 100) {
            return String.format("订单号:%s,退款金额:%.2f元,系统自动审核通过,无需人工干预", orderNo, amount);
        }

        // 无法处理,传递给下一个处理者
        if (nextHandler != null) {
            return nextHandler.handleRefund(request);
        }

        // 无下一个处理者,审核失败
        return String.format("订单号:%s,无对应审核者,审核失败", orderNo);
    }
}

(2)客服审核者(处理100-1000元退款)

// 具体处理者:客服审核者,处理100-1000元(含)的退款
public class CustomerServiceHandler implements RefundHandler {
    // 下一个处理者
    private RefundHandler nextHandler;

    // 设置下一个处理者
    @Override
    public void setNextHandler(RefundHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    // 处理退款请求
    @Override
    public String handleRefund(RefundRequest request) {
        double amount = request.getAmount();
        String orderNo = request.getOrderNo();

        // 处理100-1000元的退款
        if (amount > 100 && amount <= 1000) {
            return String.format("订单号:%s,退款金额:%.2f元,客服审核通过", orderNo, amount);
        }

        // 无法处理,传递给下一个处理者
        if (nextHandler != null) {
            return nextHandler.handleRefund(request);
        }

        // 无下一个处理者,审核失败
        return String.format("订单号:%s,无对应审核者,审核失败", orderNo);
    }
}

(3)财务审核者(处理1000元以上退款)

// 具体处理者:财务审核者,处理1000元以上的退款
public class FinanceHandler implements RefundHandler {
    // 下一个处理者(此处为链条最后一个处理者,可设为null)
    private RefundHandler nextHandler;

    // 设置下一个处理者
    @Override
    public void setNextHandler(RefundHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    // 处理退款请求
    @Override
    public String handleRefund(RefundRequest request) {
        double amount = request.getAmount();
        String orderNo = request.getOrderNo();

        // 处理1000元以上的退款
        if (amount > 1000) {
            return String.format("订单号:%s,退款金额:%.2f元,财务审核通过", orderNo, amount);
        }

        // 无法处理,传递给下一个处理者(若有)
        if (nextHandler != null) {
            return nextHandler.handleRefund(request);
        }

        // 无下一个处理者,审核失败
        return String.format("订单号:%s,无对应审核者,审核失败", orderNo);
    }
}

4. 第四步:构建责任链并进行客户端测试

// 客户端测试:电商订单退款审核场景
public class ChainOfResponsibilityPatternTest {
    public static void main(String[] args) {
        // 1. 创建具体处理者对象
        RefundHandler systemAutoHandler = new SystemAutoHandler();
        RefundHandler customerServiceHandler = new CustomerServiceHandler();
        RefundHandler financeHandler = new FinanceHandler();

        // 2. 构建责任链:系统自动审核 → 客服审核 → 财务审核
        systemAutoHandler.setNextHandler(customerServiceHandler);
        customerServiceHandler.setNextHandler(financeHandler);

        // 3. 测试不同金额的退款请求
        System.out.println("=== 测试1:退款金额80元(系统自动审核) ===");
        RefundRequest request1 = new RefundRequest("ORDER001", 80.0);
        System.out.println(systemAutoHandler.handleRefund(request1));

        System.out.println("\n=== 测试2:退款金额500元(客服审核) ===");
        RefundRequest request2 = new RefundRequest("ORDER002", 500.0);
        System.out.println(systemAutoHandler.handleRefund(request2));

        System.out.println("\n=== 测试3:退款金额1500元(财务审核) ===");
        RefundRequest request3 = new RefundRequest("ORDER003", 1500.0);
        System.out.println(systemAutoHandler.handleRefund(request3));

        System.out.println("\n=== 测试4:退款金额0元(无效金额) ===");
        RefundRequest request4 = new RefundRequest("ORDER004", 0.0);
        System.out.println(systemAutoHandler.handleRefund(request4));

        System.out.println("\n=== 测试5:动态调整责任链(跳过客服审核,系统→财务) ===");
        // 重新构建责任链:系统自动审核 → 财务审核(跳过客服)
        systemAutoHandler.setNextHandler(financeHandler);
        RefundRequest request5 = new RefundRequest("ORDER005", 800.0);
        System.out.println(systemAutoHandler.handleRefund(request5));

        System.out.println("\n=== 测试6:无对应审核者(退款金额异常,链条无处理者) ===");
        // 构建短链条:仅系统自动审核
        systemAutoHandler.setNextHandler(null);
        RefundRequest request6 = new RefundRequest("ORDER006", 200.0);
        System.out.println(systemAutoHandler.handleRefund(request6));
    }
}

运行结果

=== 测试1:退款金额80元(系统自动审核) ===
订单号:ORDER001,退款金额:80.00元,系统自动审核通过,无需人工干预

=== 测试2:退款金额500元(客服审核) ===
订单号:ORDER002,退款金额:500.00元,客服审核通过

=== 测试3:退款金额1500元(财务审核) ===
订单号:ORDER003,退款金额:1500.00元,财务审核通过

=== 测试4:退款金额0元(无效金额) ===
订单号:ORDER004,退款金额无效(0.00元),审核失败

=== 测试5:动态调整责任链(跳过客服审核,系统→财务) ===
订单号:ORDER005,退款金额:800.00元,无对应审核者,审核失败

=== 测试6:无对应审核者(退款金额异常,链条无处理者) ===
订单号:ORDER006,无对应审核者,审核失败

从运行结果可以看出,责任链模式成功实现了电商订单退款审核功能:退款请求沿着“系统自动审核→客服审核→财务审核”的链条传递,每个处理者只处理自己范围内的退款请求,无法处理则传递给下一个处理者;支持动态调整责任链(如跳过客服审核),无需修改原有处理者代码,灵活性极强;请求者只需提交退款请求,无需关心审核流程和审核者,实现了请求与处理者的解耦。同时,新增审核者(如主管审核)时,只需新增具体处理者类,加入责任链即可,符合开闭原则,扩展性强。测试5中跳过客服审核后,800元退款无对应处理者,返回审核失败,体现了链条的完整性对请求处理的影响;测试4中无效金额被系统自动审核者直接拦截,避免了请求无效传递。

五、责任链模式的高频应用场景

责任链模式适用于所有需要将请求分发到多个处理者,且需要解耦请求发送者与处理者,支持动态调整处理流程的业务场景,核心作用是请求的链式处理与解耦,以下是四大高频落地场景:

1. 审批流程场景(最经典应用)
各类审批流程中,请求需要经过多个审批节点,每个节点负责不同的审批范围,是责任链模式最核心的应用场景:

  • 请假审批:员工请假→部门主管审批→经理审批→总经理审批,按请假天数分配审批者;
  • 费用报销审批:报销申请→部门主管审批→财务审批→总经理审批(大额报销),按报销金额分配审批者;
  • 订单审批:订单提交→风控审核→财务审核→发货审核,按订单金额、类型分配审核者。

2. 拦截器/过滤器场景
前后端系统中,请求需要经过多个拦截器、过滤器处理,每个拦截器/过滤器负责不同的处理逻辑,构成责任链:

  • 后端接口拦截器:请求→登录校验拦截器→权限校验拦截器→参数校验拦截器→接口业务处理,依次拦截处理;
  • 前端请求过滤器:请求→跨域过滤器→请求参数过滤→日志记录过滤器→接口调用,依次过滤处理;
  • 日志拦截器链:系统日志→请求日志拦截器→响应日志拦截器→异常日志拦截器,依次处理日志。

3. 异常处理场景
系统异常处理中,不同类型的异常由不同的异常处理器处理,构成异常处理责任链:

  • 后端异常处理:异常→业务异常处理器→系统异常处理器→未知异常处理器,依次处理不同类型的异常;
  • 前端异常处理:异常→接口请求异常处理器→渲染异常处理器→全局异常处理器,依次捕获并处理异常;
  • 日志异常处理:日志记录异常→文件日志异常处理器→数据库日志异常处理器→远程日志异常处理器,依次尝试处理异常。

4. 框架底层与工具类设计
主流开源框架和工具类中,大量使用责任链模式实现请求的链式处理,提升框架的灵活性:

  • Spring框架:Spring MVC的拦截器(HandlerInterceptor),通过拦截器链对请求进行拦截处理;Spring Security的过滤器链,对请求进行安全校验;
  • Java Servlet:Servlet的Filter过滤器链,对请求和响应进行过滤处理;
  • 日志框架:Logback、Log4j的日志处理器链,不同级别的日志由不同的处理器处理,依次传递。

六、责任链模式 vs 命令模式(重点区分)

责任链模式与上一篇学习的命令模式,都属于行为型模式,且都实现了请求与处理者的解耦,但核心目标、使用场景、核心逻辑完全不同,极易混淆,通过表格清晰对比,帮大家彻底区分:

对比维度 责任链模式 命令模式
核心目标 将处理者连成链条,实现请求的链式分发与处理,解耦请求发送者与处理者 封装请求,解耦发送者与接收者,支持请求的排队、撤销、重做
核心逻辑 请求沿着处理者链条传递,每个处理者判断是否能处理,能处理则执行,否则传递给下一个 调用者发送命令,具体命令关联接收者,接收者执行命令,实现请求的发送与执行解耦
适用场景 请求需要多个处理者依次处理,支持动态调整处理流程(关注“请求分发”) 需要封装请求、解耦发送与执行,支持命令排队、撤销、日志(关注“请求管理”)
核心角色 抽象处理者、具体处理者、请求者 抽象命令、具体命令、接收者、调用者
核心关注点 处理者的链式组织与请求的分发,处理者之间的传递关系 请求的封装与管理,发送者与接收者的解耦,命令的灵活操作

一句话总结:责任链模式管“请求的链式分发与处理,处理者按顺序传递请求”,命令模式管“请求的封装与管理,发送者与接收者解耦”;请求需要多个处理者依次处理、动态调整流程用责任链模式,需要封装请求、支持撤销/排队用命令模式,两者可结合使用(如审批流程中,用责任链模式分发审批请求,用命令模式封装每个审批操作)。

七、责任链模式的常见坑与避坑指南

坑1:责任链断裂,导致请求无法处理

部分开发者在构建责任链时,忘记设置处理者的下一个处理者,或链条末端没有处理所有剩余请求的处理者,导致请求传递到链条末端后无法处理,出现业务异常。
避坑指南:构建责任链时,确保每个处理者(除末端处理者)都正确设置下一个处理者;链条末端设置一个“默认处理者”,负责处理所有未被前面处理者处理的请求,返回明确的失败提示,避免请求无法处理。

坑2:处理者职责模糊,导致请求重复处理或漏处理

部分开发者在设计具体处理者时,没有明确每个处理者的处理范围,导致多个处理者处理同一个请求(重复处理),或某个请求没有任何处理者能处理(漏处理)。
避坑指南:明确每个具体处理者的处理范围,确保处理范围不重叠、不遗漏;可通过文档或注释明确每个处理者的职责和处理条件;在抽象处理者中添加日志记录,跟踪请求的传递和处理过程,便于排查问题。

坑3:责任链过长,导致请求处理效率低下

若责任链中的处理者过多,请求需要经过多个处理者传递才能被处理,会导致请求处理效率低下,尤其是在高并发场景中,影响系统性能。
避坑指南:合理拆分责任链,将处理逻辑相近的处理者合并,减少处理者数量;对责任链进行分层,按处理优先级构建多个短链条,避免单一链条过长;在高并发场景中,可通过缓存常用请求的处理结果,提升处理效率。

坑4:过度使用责任链模式,简化场景复杂化

部分开发者在请求只需单个处理者处理、无需链式传递的场景中,强行使用责任链模式,新增抽象处理者、具体处理者,构建责任链,导致代码冗余、逻辑晦涩,反而降低了开发效率。
避坑指南:只有当请求需要多个处理者依次处理、需要动态调整处理流程,且需要解耦请求发送者与处理者时,才使用责任链模式;请求只需单个处理者处理的场景,直接调用处理者的方法即可,无需过度设计。

坑5:动态调整链条时,导致逻辑混乱

部分开发者在动态调整责任链(如添加、删除、调整处理者顺序)时,没有考虑处理者之间的依赖关系,导致请求传递逻辑混乱,出现处理顺序错误、请求无法传递等问题。
避坑指南:动态调整责任链时,明确处理者的处理顺序和依赖关系,避免调整后出现处理逻辑冲突;可通过工厂模式或建造者模式,统一管理责任链的构建和调整,确保链条结构正确;调整后进行充分测试,验证请求传递和处理逻辑是否正常。

八、系列文章预告

本篇文章,我们详细讲解了责任链模式的核心定义、三个核心角色、标准执行流程、电商订单退款审核实战代码、高频应用场景和避坑指南,同时区分了易混淆的命令模式。责任链模式凭借“请求链式处理、解耦发送与执行、支持动态调整流程”的优势,成为需要多处理者依次处理请求场景的首选设计模式,能够大幅提升系统的灵活性、可维护性和可扩展性,也是审批流程、拦截器链、异常处理的核心设计思想之一。
下一篇,我们将学习行为型模式的第二十五种常用模式——中介者模式,它的核心是定义一个中介者对象,封装多个对象之间的交互关系,使各个对象无需直接相互引用,而是通过中介者进行通信,从而降低对象之间的耦合度,简化对象间的交互逻辑。中介者模式专注于“对象间交互的解耦”,广泛应用于对象间交互复杂、耦合度高的场景,如聊天系统、电商订单调度系统、团队协作系统等。
中介者模式——封装对象交互,降低耦合度。我们不见不散!

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐