设计模式学习(25) 23-23 责任链模式

文章目录

  • [0. 个人感悟](#0. 个人感悟)
  • [1. 概念](#1. 概念)
  • [2. 适配场景](#2. 适配场景)
    • [2.1 适合的场景](#2.1 适合的场景)
    • [2.2 常见场景举例](#2.2 常见场景举例)
  • [3. 实现方法](#3. 实现方法)
    • [3.1 实现思路](#3.1 实现思路)
    • [3.2 UML类图](#3.2 UML类图)
    • [3.3 代码示例](#3.3 代码示例)
  • [4. 优缺点](#4. 优缺点)
    • [4.1 优点](#4.1 优点)
    • [4.2 缺点](#4.2 缺点)
  • [5. 源码分析](#5. 源码分析)

0. 个人感悟

  • 责任链模式如其名,让接受者都有机会处理消息,链式调用
  • 传统方式按流程来累代码,处理消息的代码会有很多的if-else判断由谁来处理,这样不仅职责不单一,而且需要了解处理者的实现逻辑,耦合太重;责任链模式可以让消息发送者和处理者解耦,发送者不需要知道谁来处理,各个处理者只需要做好自己的业务和消息传递就好
  • 类似于现实中"踢皮球"或"层层审批"的流程
  • 可以和模版方法模式配合,抽象一个基础handler,后面代码里有示例,有兴趣可以看看

1. 概念

英文定义 (《设计模式:可复用面向对象软件的基础》)

Avoid coupling the sender of request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

中文翻译

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

理解

  • 解耦请求发送者和接收者,发送者不需要知道谁来处理请求
  • 多个处理器对象组成一条链,请求沿着链传递
  • 每个处理器决定是否处理请求,以及是否传递给下一个处理器
  • 核心是处理器的"链式"组织和请求的"传递"机制

2. 适配场景

2.1 适合的场景

  • 多级审批系统:请假、报销、采购等需要多级审批的业务流程
  • 过滤器和拦截器:Web框架中的过滤器链、拦截器链
  • 事件处理:GUI中的事件传递,如按钮点击事件冒泡
  • 异常处理:不同级别的异常由不同的处理器处理
  • 日志记录:不同级别的日志信息由不同的处理器记录
  • 责任分离:将复杂的处理逻辑分解为多个小处理器
  • 动态可配置的处理流程:处理流程可以运行时动态调整

2.2 常见场景举例

  1. 请假审批系统:员工提交请假申请 → 组长审批 → 经理审批 → HR备案
  2. Web请求处理:请求 → 字符编码过滤器 → 安全过滤器 → 日志过滤器 → 业务处理
  3. Java异常处理:try-catch-finally,异常沿着调用栈向上传递
  4. 日志系统:DEBUG → INFO → WARN → ERROR,不同级别的日志由不同处理器处理
  5. 游戏事件处理:鼠标点击事件 → UI系统 → 游戏对象系统 → 物理引擎

3. 实现方法

3.1 实现思路

  1. 定义抽象处理器接口/抽象类

    • 声明处理请求的方法
    • 定义设置后继处理器的方法
    • 可选:定义处理请求的模板方法
  2. 实现具体处理器类

    • 实现处理逻辑,判断是否能够处理当前请求
    • 如果可以处理,则处理请求并终止传递
    • 如果不能处理,则传递给后继处理器
  3. 构建处理链

    • 创建处理器实例
    • 按顺序链接处理器,形成处理链
    • 可结合建造者模式简化链的构建
  4. 客户端使用

    • 创建请求对象
    • 将请求提交给处理链的第一个处理器
    • 无需关心具体由哪个处理器处理

3.2 UML类图

角色说明

  • Handler (抽象处理器):定义处理请求的接口,维护后继处理器引用
  • ConcreteHandler (具体处理器):实现处理逻辑,处理可处理的请求,否则传递
  • Client (客户端):创建处理链并提交请求
  • Request (请求):封装请求信息和数据

3.3 代码示例

背景

以金额审批为例

  • 角色包括经理、总监、CEO,对于不同金额有不同处理结果
  • 实现上抽了一层AbstractHandler,配合模版方法

处理器接口

java 复制代码
public interface Handler {  
    /**  
     * @param request 请求  
     * @description 处理请求  
     * @author bigHao  
     * @date 2026/1/28  
     **/    
     void handleRequest(Request request);  
  
    /**  
     * @param next 下个处理器  
     * @description 设置下一个处理器  
     * @author bigHao  
     * @date 2026/1/28  
     **/    
     void setNext(Handler next);  
}

处理器基础实现

java 复制代码
public abstract class AbstractHandler implements Handler {  
  
    protected String name;  
  
    protected Handler nextHandler;  
  
    public AbstractHandler(String name) {  
        this.name = name;  
    }  
  
    @Override  
    public void handleRequest(Request request) {  
        if (canHandle(request)) {  
            System.out.println(STR."\{name} 可以处理 ");  
            process(request);  
        } else {  
            System.out.println(STR."\{name} 不可以处理 ");  
            nextHandler.handleRequest(request);  
        }  
    }  
  
    @Override  
    public void setNext(Handler next) {  
        this.nextHandler = next;  
    }  
  
  
    /**  
     * @param request 请求  
     * @return boolean 结果  
     * @description 是否可以处理  
     * @author bigHao  
     * @date 2026/1/28  
     **/    
     abstract boolean canHandle(Request request);  
  
    /**  
     * @param request 请求  
     * @description 执行请求  
     * @author bigHao  
     * @date 2026/1/28  
     **/    
     abstract void process(Request request);  
}

处理器子类

java 复制代码
public class ManagerHandler extends AbstractHandler {  
    public ManagerHandler(String name) {  
        super(name);  
    }  
  
    @Override  
    boolean canHandle(Request request) {  
        return request.getAmount() <= 1000;  
    }  
  
    @Override  
    void process(Request request) {  
        System.out.println("经理已经处理");  
    }  
}

public class DirectorHandler extends AbstractHandler {  
    public DirectorHandler(String name) {  
        super(name);  
    }  
  
    @Override  
    boolean canHandle(Request request) {  
        return request.getAmount() <= 10000;  
    }  
  
    @Override  
    void process(Request request) {  
        System.out.println(name + "已经处理");  
    }  
}

public class CEOHandler extends AbstractHandler {  
    public CEOHandler(String name) {  
        super(name);  
    }  
  
    @Override  
    boolean canHandle(Request request) {  
        return true;  
    }  
  
    @Override  
    void process(Request request) {  
        System.out.println(name + "已经处理");  
    }  
}

辅助类

java 复制代码
public class Request {  
    private int amount;  
  
    public Request(int amount) {  
        this.amount = amount;  
    }  
  
    public int getAmount() {  
        return amount;  
    }  
  
    public void setAmount(int amount) {  
        this.amount = amount;  
    }  
}

测试

java 复制代码
public class Client {  
    static void main() {  
        // 设置调用链  
        Handler manager = new ManagerHandler("张经理");  
        Handler director = new DirectorHandler("李总监");  
        Handler ceo = new CEOHandler("王CEO");  
  
        manager.setNext(director);  
        director.setNext(ceo);  
        Request request = new Request(2000);  
  
        manager.handleRequest(request);  
    }  
}

结果

复制代码
张经理 不可以处理 
李总监 可以处理 
李总监已经处理

4. 优缺点

4.1 优点

高内聚低耦合

  • 发送者与接收者解耦,发送者无需知道具体处理器
  • 处理器之间松耦合,可以独立变化和复用

复用性与可维护性

  • 处理器职责单一,易于复用
  • 可以动态添加、删除或修改处理器顺序,扩展性好
  • 符合开闭原则,新增处理器无需修改现有代码

灵活性与可读性

  • 处理流程清晰可见,易于理解和调试
  • 可以灵活组合处理器形成不同的处理链

4.2 缺点

性能与稳定性

  • 链过长可能影响性能,请求需要遍历多个处理器
  • 如果链配置不当,请求可能无法被处理(丢失请求)
  • 调试较困难,需要跟踪请求在链中的传递过程

其他考虑

  • 需要确保链中至少有一个处理器能处理请求,否则请求丢失
  • 处理器之间的顺序依赖可能隐含业务逻辑,不易察觉

5. 源码分析

有兴趣可以了解下Spring MVC中的责任链模式,我计划后面专门整理Spring相关内容


参考:

相关推荐
im_AMBER2 小时前
消失的最后一秒:SSE 流式联调中的“时序竞争”
前端·笔记·学习·http·sse
Gain_chance2 小时前
24-学习笔记尚硅谷数仓搭建-DIM层的维度表建表思路及商品表维度表的具体建表解析
数据仓库·hive·笔记·学习·datagrip
求真求知的糖葫芦2 小时前
RF and Microwave Coupled-Line Circuits射频微波耦合线电路4.2 使用均匀耦合线的方向性耦合器学习笔记(自用)
笔记·学习·线性代数·射频工程
子夜江寒2 小时前
OpenCV 学习:从光流跟踪到艺术风格迁移
opencv·学习·计算机视觉
半桔2 小时前
【设计模式】策略模式:可插拔算法,从硬编码到灵活适配,体会“算法解耦“思想
java·c++·算法·设计模式·策略模式
QiZhang | UESTC2 小时前
学习日记day71
学习
ddxu2 小时前
AI学习笔记
笔记·学习·ai
Engineer邓祥浩2 小时前
设计模式学习(23) 23-21 状态模式
学习·设计模式·状态模式
肥硕之虎2 小时前
渗透高级课个人学习分享
学习