rokevin
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
  • 责任链模式(Chain of Responsibility Pattern)

  • 一、定义
  • 二、意图
  • 三、结构
  • 四、优点
  • 五、缺点
  • 六、类图(Mermaid)
  • 七、时序图(Mermaid)
  • 八、适用环境
  • 九、模式分析
  • 十、模式扩展
  • 十一、模式应用
  • 十二、Android 中的应用
  • 十三、代码实现(Java 版)
    • 1. 定义请求对象(Request)
    • 2. 定义抽象处理者(Handler)
    • 3. 定义具体处理者(ConcreteHandler)
    • 4. 客户端(Client)
    • 5. 运行结果
  • 十四、总结

责任链模式(Chain of Responsibility Pattern)

责任链模式是一种行为型设计模式,其核心思想是将请求的发送者与接收者解耦,通过构建一条 “接收者链”,让请求在链上传递,直到有一个接收者能够处理该请求为止。这种模式避免了请求发送者与具体处理者之间的直接依赖,增强了系统的灵活性和可扩展性。

一、定义

官方定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

通俗理解:类比生活中的 “审批流程”(如报销审批:员工→部门经理→财务总监→CEO),报销单(请求)会从链的起点开始传递,每个审批人(处理者)判断自己是否有权限处理,有权限则处理,无权限则传递给下一个审批人,直到请求被处理或链结束。

二、意图

  1. 解耦请求发送者与处理者:发送者无需知道请求由哪个处理者处理,只需将请求提交到链上即可。
  2. 动态组合处理流程:可通过动态调整链中处理者的顺序或增减处理者,灵活修改请求的处理逻辑。
  3. 避免请求发送者与多个处理者的直接关联:减少类之间的依赖,降低系统复杂度。

三、结构

责任链模式的核心结构包含4 个角色,各角色职责明确,协同完成请求的传递与处理:

角色名称核心职责
抽象处理者(Handler)定义处理请求的接口(如 handleRequest() 方法),并维护一个 “下一个处理者” 的引用。
具体处理者(ConcreteHandler)实现抽象处理者的接口,判断自身是否能处理请求: - 能处理:直接处理请求; - 不能处理:将请求传递给 “下一个处理者”。
请求对象(Request)封装请求的相关信息(如请求类型、请求内容、请求优先级等),供处理者判断是否处理。
客户端(Client)创建具体处理者对象,构建责任链,并将请求提交到链的起点(第一个处理者)。

四、优点

  1. 解耦发送者与处理者:发送者无需知道请求的具体处理者,处理者也无需知道发送者,两者通过链间接通信。
  2. 灵活性高:可动态调整链中处理者的顺序、增减处理者,无需修改原有代码(符合开闭原则)。
  3. 单一职责:每个具体处理者只需关注自身职责范围内的请求处理,逻辑清晰,便于维护。
  4. 简化客户端代码:客户端只需将请求提交到链的起点,无需关心后续处理流程。

五、缺点

  1. 请求可能 “丢失”:若链中所有处理者都无法处理请求,且未设置 “默认处理者”,请求会被丢弃,可能导致业务异常。
  2. 性能开销:请求需从链的起点依次传递到处理者,若链过长,会增加请求处理的延迟。
  3. 调试复杂度高:请求的处理路径分散在多个处理者中,问题排查时需跟踪整个链的传递过程。

六、类图(Mermaid)

classDiagram
    direction TB
    class Handler {
        +Handler nextHandler
        +setNextHandler(Handler): void
        +abstract handleRequest(Request): void
    }
    class ConcreteHandlerA {
        +handleRequest(Request): void
    }
    class ConcreteHandlerB {
        +handleRequest(Request): void
    }
    class ConcreteHandlerC {
        +handleRequest(Request): void
    }
    class Request {
        -requestType: String
        -requestContent: String
        -priority: int
        +getRequestType(): String
        +getRequestContent(): String
        +getPriority(): int
    }
    class Client {
        +main(): void
    }

    Handler <|-- ConcreteHandlerA
    Handler <|-- ConcreteHandlerB
    Handler <|-- ConcreteHandlerC
    Handler "1" --> "0..1" Handler : has next
    Client --> Handler : creates & builds chain
    Client --> Request : creates
    Handler --> Request : processes

七、时序图(Mermaid)

以 “报销审批” 为例,时序图展示请求(报销单)在链中传递的过程:

sequenceDiagram
    participant Client
    participant EmpHandler as 员工(链起点)
    participant MgrHandler as 部门经理
    participant FinHandler as 财务总监(链终点)
    participant Request as 报销单(请求)

    %% 1. 客户端创建请求和处理者,构建责任链
    Client->>Request: 创建报销单(金额5000元)
    Client->>EmpHandler: 创建员工处理者
    Client->>MgrHandler: 创建部门经理处理者
    Client->>FinHandler: 创建财务总监处理者
    Client->>EmpHandler: 设置下一个处理者(部门经理)
    Client->>MgrHandler: 设置下一个处理者(财务总监)

    %% 2. 客户端提交请求到链起点
    Client->>EmpHandler: 提交报销请求
    EmpHandler->>EmpHandler: 判断:无审批权限(仅发起)
    EmpHandler->>MgrHandler: 传递请求(报销5000元)
    
    %% 3. 部门经理处理请求
    MgrHandler->>MgrHandler: 判断:权限≤3000元,5000元超权限
    MgrHandler->>FinHandler: 传递请求(报销5000元)
    
    %% 4. 财务总监处理请求
    FinHandler->>FinHandler: 判断:权限≤10000元,5000元符合权限
    FinHandler->>Client: 反馈:报销审批通过

八、适用环境

当系统满足以下场景时,适合使用责任链模式:

  1. 有多个对象可能处理同一个请求,但具体处理者需在运行时确定(如审批流程、日志级别处理)。
  2. 需动态指定请求的处理流程(如可配置的过滤链、拦截器链)。
  3. 请求发送者不希望与具体处理者耦合(如框架设计中,用户无需关心内部处理逻辑)。
  4. 需避免请求发送者与多个处理者直接关联(如避免大量 if-else 或 switch 判断处理者)。

九、模式分析

  1. 链的构建方式:
    • 客户端构建:客户端明确知道所有处理者,手动组装链(如示例中客户端设置 nextHandler)。
    • 处理者自构建:处理者在初始化时自动关联下一个处理者(减少客户端依赖,但灵活性降低)。
  2. 请求的传递逻辑:
    • 单向传递:请求从链的起点到终点,仅沿一个方向传递(最常见)。
    • 循环传递:链的终点关联起点,请求循环传递(需避免死循环,适用于特殊场景)。
  3. 处理者的判断逻辑:
    • 排他处理:仅一个处理者处理请求(如审批流程,仅最终审批人处理)。
    • 叠加处理:多个处理者依次处理请求(如过滤器链,每个过滤器都处理请求)。

十、模式扩展

责任链模式可根据业务需求进行扩展,常见扩展形式如下:

  1. 带默认处理者的责任链:在链的终点添加 “默认处理者”,若所有处理者无法处理请求,由默认处理者兜底(避免请求丢失)。
  2. 可中断的责任链:处理者处理请求后,可选择是否继续传递请求(如叠加处理场景,处理后继续传递;排他处理场景,处理后中断传递)。
  3. 带优先级的责任链:请求携带优先级,处理者仅处理指定优先级的请求(如日志系统,ERROR 级日志由控制台 + 文件处理,INFO 级日志仅由文件处理)。
  4. 动态调整的责任链:运行时可动态添加 / 移除处理者(如插件化架构,通过插件动态扩展处理逻辑)。

十一、模式应用

责任链模式在框架和业务系统中应用广泛,典型场景包括:

  1. 框架层面:
    • Java Servlet 的 Filter 链:请求经过多个过滤器处理(如登录验证、字符编码过滤、权限检查)。
    • Spring 的 Interceptor 链:Spring MVC 中请求经过多个拦截器处理。
    • Netty 的 ChannelPipeline:网络请求经过多个 ChannelHandler 处理(解码、编码、业务处理)。
  2. 业务层面:
    • 审批流程:报销审批、请假审批、采购审批等。
    • 日志系统:不同级别日志(DEBUG/INFO/WARN/ERROR)由不同处理器处理。
    • 异常处理:不同类型异常(NullPointerException/IllegalArgumentException)由不同异常处理器处理。
    • 订单处理:订单状态流转(待支付→已支付→待发货→已发货→已完成),每个状态由对应处理器处理。

十二、Android 中的应用

在 Android 开发中,责任链模式的典型应用如下:

  1. 事件分发机制: Android 的 View 事件分发(dispatchTouchEvent/onInterceptTouchEvent/onTouchEvent)本质是责任链模式:
    • 链结构:Activity → PhoneWindow → DecorView → ViewGroup → View。
    • 事件传递:触摸事件从 Activity 开始向下传递,ViewGroup 可拦截事件(onInterceptTouchEvent 返回 true),若不拦截则传递给子 View,直到 View 处理事件(onTouchEvent 返回 true)或事件传递到链终点。
  2. BroadcastReceiver 有序广播: 有序广播(sendOrderedBroadcast)按优先级从高到低传递,每个 BroadcastReceiver 可处理广播,也可通过 abortBroadcast() 中断广播传递(类似可中断的责任链)。
  3. OkHttp 的 Interceptor 链: OkHttp 中请求经过多个拦截器处理(如 RetryAndFollowUpInterceptor、BridgeInterceptor、CacheInterceptor、CallServerInterceptor),每个拦截器处理后将请求传递给下一个拦截器,最终完成网络请求。

十三、代码实现(Java 版)

以 “报销审批” 为例,实现责任链模式:

1. 定义请求对象(Request)

封装报销请求的信息(金额、申请人):

// 请求对象:报销单
public class ExpenseRequest {
    // 报销金额
    private double amount;
    // 申请人
    private String applicant;

    public ExpenseRequest(double amount, String applicant) {
        this.amount = amount;
        this.applicant = applicant;
    }

    // Getter 方法
    public double getAmount() {
        return amount;
    }

    public String getApplicant() {
        return applicant;
    }
}

2. 定义抽象处理者(Handler)

定义处理请求的接口,并维护下一个处理者的引用:

// 抽象处理者:审批人
public abstract class Approver {
    // 下一个审批人(责任链的下一个节点)
    protected Approver nextApprover;

    // 设置下一个审批人
    public void setNextApprover(Approver nextApprover) {
        this.nextApprover = nextApprover;
    }

    // 抽象方法:处理报销请求(子类需实现)
    public abstract void processRequest(ExpenseRequest request);
}

3. 定义具体处理者(ConcreteHandler)

实现不同权限的审批人(部门经理、财务总监、CEO):

// 具体处理者1:部门经理(审批≤3000元)
public class DepartmentManager extends Approver {
    @Override
    public void processRequest(ExpenseRequest request) {
        if (request.getAmount() <= 3000) {
            // 部门经理有权限处理,直接审批
            System.out.println("部门经理审批通过:" + request.getApplicant() + " 的报销单,金额:" + request.getAmount() + "元");
        } else if (nextApprover != null) {
            // 无权限,传递给下一个审批人(财务总监)
            System.out.println("部门经理无权限审批(金额超3000元),传递给财务总监");
            nextApprover.processRequest(request);
        } else {
            // 无下一个审批人,请求无法处理
            System.out.println("部门经理无权限审批,且无后续审批人,请求丢失");
        }
    }
}

// 具体处理者2:财务总监(审批≤10000元)
public class FinanceDirector extends Approver {
    @Override
    public void processRequest(ExpenseRequest request) {
        if (request.getAmount() <= 10000) {
            System.out.println("财务总监审批通过:" + request.getApplicant() + " 的报销单,金额:" + request.getAmount() + "元");
        } else if (nextApprover != null) {
            System.out.println("财务总监无权限审批(金额超10000元),传递给CEO");
            nextApprover.processRequest(request);
        } else {
            System.out.println("财务总监无权限审批,且无后续审批人,请求丢失");
        }
    }
}

// 具体处理者3:CEO(审批≤50000元)
public class CEO extends Approver {
    @Override
    public void processRequest(ExpenseRequest request) {
        if (request.getAmount() <= 50000) {
            System.out.println("CEO审批通过:" + request.getApplicant() + " 的报销单,金额:" + request.getAmount() + "元");
        } else {
            // CEO 是链的终点,无权限则直接拒绝
            System.out.println("CEO无权限审批(金额超50000元),报销请求拒绝");
        }
    }
}

4. 客户端(Client)

构建责任链,并提交请求:

// 客户端:组装责任链并测试
public class Client {
    public static void main(String[] args) {
        // 1. 创建具体处理者
        Approver deptMgr = new DepartmentManager();
        Approver financeDir = new FinanceDirector();
        Approver ceo = new CEO();

        // 2. 构建责任链:部门经理 → 财务总监 → CEO
        deptMgr.setNextApprover(financeDir);
        financeDir.setNextApprover(ceo);

        // 3. 提交不同金额的报销请求
        System.out.println("=== 测试1:报销2000元 ===");
        deptMgr.processRequest(new ExpenseRequest(2000, "张三"));

        System.out.println("\n=== 测试2:报销8000元 ===");
        deptMgr.processRequest(new ExpenseRequest(8000, "李四"));

        System.out.println("\n=== 测试3:报销30000元 ===");
        deptMgr.processRequest(new ExpenseRequest(30000, "王五"));

        System.out.println("\n=== 测试4:报销60000元 ===");
        deptMgr.processRequest(new ExpenseRequest(60000, "赵六"));
    }
}

5. 运行结果

=== 测试1:报销2000元 ===
部门经理审批通过:张三 的报销单,金额:2000.0元

=== 测试2:报销8000元 ===
部门经理无权限审批(金额超3000元),传递给财务总监
财务总监审批通过:李四 的报销单,金额:8000.0元

=== 测试3:报销30000元 ===
部门经理无权限审批(金额超3000元),传递给财务总监
财务总监无权限审批(金额超10000元),传递给CEO
CEO审批通过:王五 的报销单,金额:30000.0元

=== 测试4:报销60000元 ===
部门经理无权限审批(金额超3000元),传递给财务总监
财务总监无权限审批(金额超10000元),传递给CEO
CEO无权限审批(金额超50000元),报销请求拒绝

十四、总结

责任链模式通过构建 “处理者链”,实现了请求发送者与接收者的解耦,核心价值在于灵活组织处理流程和减少直接依赖。其优点是灵活性高、职责单一、简化客户端代码;缺点是可能存在请求丢失、性能开销和调试复杂度问题。

在实际开发中,需根据业务场景合理设计链的长度和处理逻辑,避免过度设计(如链过长导致性能问题)。同时,可结合扩展形式(如默认处理者、优先级)优化模式,使其更贴合业务需求。

责任链模式在框架(如 Servlet Filter、OkHttp Interceptor)和业务系统(如审批流程、过滤器)中应用广泛,是解决 “多处理者协同处理请求” 问题的重要设计模式。

最近更新:: 2025/10/22 15:36
Contributors: 罗凯文, luokaiwen