深度剖析责任链模式

news2025/5/14 4:18:33

一、责任链模式的本质:灵活可扩展的流水线处理

责任链模式(Chain of Responsibility Pattern)是行为型设计模式的代表,其核心思想是将请求的发送者与接收者解耦,允许多个对象都有机会处理请求。这种模式完美解决了以下场景痛点:

  1. 动态流程编排:审批流程、风控流程等需要灵活调整顺序

  2. 请求分发机制:日志处理、权限校验等需要多层级过滤

  3. 未知处理者:异常捕获链、HTTP中间件等场景

UML类图


二、责任链模式的三种经典实现

1. 基础链表实现(传统方式)

// 处理器接口
public interface OrderHandler {
    void handle(Order order);
    void setNext(OrderHandler next);
}

// 抽象基类
public abstract class AbstractOrderHandler implements OrderHandler {
    private OrderHandler next;

    @Override
    public void setNext(OrderHandler next) {
        this.next = next;
    }

    protected void handleNext(Order order) {
        if (next != null) {
            next.handle(order);
        }
    }
}

// 具体处理器
public class InventoryCheckHandler extends AbstractOrderHandler {
    @Override
    public void handle(Order order) {
        if (!checkInventory(order)) {
            throw new RuntimeException("库存不足");
        }
        System.out.println("库存校验通过");
        handleNext(order);
    }

    private boolean checkInventory(Order order) {
        // 库存检查逻辑
        return true;
    }
}

public class PaymentHandler extends AbstractOrderHandler {
    @Override
    public void handle(Order order) {
        processPayment(order);
        System.out.println("支付处理完成");
        handleNext(order);
    }

    private void processPayment(Order order) {
        // 支付处理逻辑
    }
}

2. 集合迭代实现(Spring风格)

// 处理器接口
public interface Filter {
    void doFilter(Request request, Response response, FilterChain chain);
}

// 链式调用容器
public class FilterChain {
    private List<Filter> filters = new ArrayList<>();
    private int index = 0;

    public FilterChain addFilter(Filter filter) {
        filters.add(filter);
        return this;
    }

    public void doFilter(Request request, Response response) {
        if (index < filters.size()) {
            Filter filter = filters.get(index++);
            filter.doFilter(request, response, this);
        }
    }
}

// 使用示例
FilterChain chain = new FilterChain()
    .addFilter(new AuthFilter())
    .addFilter(new LogFilter())
    .addFilter(new EncodingFilter());
chain.doFilter(request, response);

3. 注解驱动实现(企业级方案)

// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface OrderProcessor {
    int order() default 0;
    String[] supportType();
}

// 处理器基类
public abstract class BaseOrderProcessor {
    @Autowired
    private ProcessorChain chain;

    public void process(OrderContext context) {
        if (canProcess(context)) {
            doProcess(context);
        }
        chain.process(context);
    }

    protected abstract boolean canProcess(OrderContext context);
    protected abstract void doProcess(OrderContext context);
}

// 具体处理器
@OrderProcessor(order = 1, supportType = "NORMAL")
public class NormalOrderProcessor extends BaseOrderProcessor {
    @Override
    protected boolean canProcess(OrderContext context) {
        return "NORMAL".equals(context.getOrderType());
    }

    @Override
    protected void doProcess(OrderContext context) {
        // 普通订单处理逻辑
    }
}

三、责任链模式的五大应用场景

场景1:审批流程系统

  • 请假审批链(组长 → 经理 → 总监)

  • 采购审批链(金额分级审批)

  • 合同审批链(法务 → 财务 → CEO)

场景2:Web请求处理

  • Servlet Filter链

  • Spring Interceptor链

  • 网关过滤器链(限流 → 鉴权 → 日志)

场景3:订单处理系统

  • 订单校验链(库存 → 优惠券 → 地址)

  • 订单履约链(拆单 → 分配仓库 → 物流)

场景4:异常处理系统

  • 异常捕获链(业务异常 → 系统异常 → 全局异常)

  • 错误恢复链(重试 → 降级 → 告警)

场景5:游戏事件处理

  • 技能释放链(蓝量检查 → CD检查 → 效果触发)

  • 伤害计算链(防御计算 → 暴击计算 → 元素反应)


四、责任链模式与相关模式对比

模式关注点与责任链的区别
装饰器模式增强对象功能责任链强调传递,装饰器强调叠加功能
命令模式请求封装责任链处理请求传递,命令模式处理请求封装与执行
组合模式树形结构责任链是线性结构,组合模式是树状结构
策略模式算法替换责任链多个处理器协作,策略模式单个算法替换

五、企业级实战:Spring风格审批系统

架构设计

[审批请求] → [审批链构建器] → [审批处理器1] → [审批处理器2] → [...] → [审批完成]
                   ↑
           [审批规则配置中心]
                   ↑
           [数据库/配置中心]

完整代码实现

// 审批处理器接口
public interface ApprovalHandler {
    ApprovalResult handle(ApprovalContext context);
    void setNext(ApprovalHandler next);
    boolean support(ApprovalType type);
}

// 链式处理器基类
public abstract class AbstractApprovalHandler implements ApprovalHandler {
    private ApprovalHandler next;
    private ApprovalType supportType;

    protected AbstractApprovalHandler(ApprovalType supportType) {
        this.supportType = supportType;
    }

    @Override
    public void setNext(ApprovalHandler next) {
        this.next = next;
    }

    @Override
    public ApprovalResult handle(ApprovalContext context) {
        if (!support(context.getType())) {
            return next.handle(context);
        }

        ApprovalResult result = doHandle(context);
        if (result.isApproved() && next != null) {
            return next.handle(context);
        }
        return result;
    }

    @Override
    public boolean support(ApprovalType type) {
        return this.supportType == type;
    }

    protected abstract ApprovalResult doHandle(ApprovalContext context);
}

// 具体审批处理器
public class DepartmentManagerHandler extends AbstractApprovalHandler {
    public DepartmentManagerHandler() {
        super(ApprovalType.DEPARTMENT_MANAGER);
    }

    @Override
    protected ApprovalResult doHandle(ApprovalContext context) {
        // 部门经理审批逻辑
        return new ApprovalResult(true, "部门经理审批通过");
    }
}

// 审批链构建工厂
@Service
public class ApprovalChainFactory {
    @Autowired
    private List<ApprovalHandler> handlers;

    public ApprovalHandler createChain(ApprovalType type) {
        List<ApprovalHandler> sortedHandlers = handlers.stream()
                .filter(h -> h.support(type))
                .sorted(Comparator.comparingInt(h -> h.getOrder()))
                .collect(Collectors.toList());

        ApprovalHandler head = null;
        ApprovalHandler current = null;
        for (ApprovalHandler handler : sortedHandlers) {
            if (head == null) {
                head = handler;
                current = handler;
            } else {
                current.setNext(handler);
                current = handler;
            }
        }
        return head;
    }
}

六、责任链模式的五大优化技巧

1. 动态配置链顺序

// 基于配置文件的链定义
@Configuration
public class ChainConfig {
    @Bean
    public FilterChain securityFilterChain() {
        return new FilterChain()
            .addFilter(new CorsFilter())
            .addFilter(new AuthFilter())
            .addFilter(new RateLimitFilter());
    }
}

2. 中断机制优化

public interface Handler {
    enum Result {
        CONTINUE, BREAK
    }
    Result handle(Request request);
}

public class Chain {
    public void process(Request request) {
        for (Handler handler : handlers) {
            if (handler.handle(request) == Result.BREAK) {
                return;
            }
        }
    }
}

3. 性能监控埋点

public class MonitoredHandler implements Handler {
    private final Handler delegate;
    private final MeterRegistry registry;

    public MonitoredHandler(Handler delegate, MeterRegistry registry) {
        this.delegate = delegate;
        this.registry = registry;
    }

    @Override
    public Result handle(Request request) {
        Timer.Sample sample = Timer.start(registry);
        try {
            return delegate.handle(request);
        } finally {
            sample.stop(registry.timer("handler.time", 
                "handler", delegate.getClass().getSimpleName()));
        }
    }
}

七、常见陷阱与解决方案

陷阱现象解决方案
循环引用链式调用死循环增加最大调用深度检测
处理器遗漏请求未被任何处理器处理设置默认处理器或抛出明确异常
顺序依赖错误处理器执行顺序不符合预期使用优先级注解明确顺序
性能瓶颈长链路导致延迟过高引入异步处理或并行执行
状态污染处理器之间共享可变状态使用ThreadLocal或深拷贝上下文

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2298273.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

floodfill算法系列一>岛屿的最大面积

题解 整体思路&#xff1a;代码设计&#xff1a;代码呈现&#xff1a; 整体思路&#xff1a; 代码设计&#xff1a; 代码呈现&#xff1a; class Solution {int ret,m,n,count;boolean[][] vis;public int maxAreaOfIsland(int[][] grid) {m grid.length;n grid[0].length;v…

手机用流量怎样设置代理ip?

互联网各领域资料分享专区(不定期更新)&#xff1a; Sheet

游戏引擎学习第100天

仓库:https://gitee.com/mrxiao_com/2d_game_2 昨天的回顾 今天的工作重点是继续进行反射计算的实现。昨天&#xff0c;我们开始了反射和环境贴图的工作&#xff0c;成功地根据法线显示了反射效果。然而&#xff0c;我们还没有实现反射向量的计算&#xff0c;导致反射交点的代…

AT32系列微控制器低压电机控制开发板

参考&#xff1a;《UM0014_AT32_LV_Motor_Control_EVB_V20_User_Manual_V1.0.1_ZH.pdf》 开发板介绍 此电机开发板是一个泛用型的低压三相电机驱动器&#xff0c;应用雅特力科技AT32系列微控制器搭配雅特力电机函数库&#xff0c;可驱动直流无刷电机、交流同步电机&#xff0…

如何保持 mysql 和 redis 中数据的一致性?PegaDB 给出答案

MySQL 与 Redis 数据保持一致性是一个常见且复杂的问题&#xff0c;一般来说需要结合多种策略来平衡性能与一致性。 传统的解决策略是先读缓存&#xff0c;未命中则读数据库并回填缓存&#xff0c;但方式这种维护成本较高。 随着云数据库技术的发展&#xff0c;目前国内云厂商…

Vue3(3)

一.具体业务功能实现 &#xff08;1&#xff09;登录注册页面 [element-plus 表单 & 表单校验] 功能需求说明&#xff1a; 1.注册登录 静态结构 & 基本切换 2.注册功能 (校验 注册) 3.登录功能 (校验 登录 存token) import request from /utils/request// 注册接…

2025 西湖论剑wp

web Rank-l 打开题目环境&#xff1a; 发现一个输入框&#xff0c;看一下他是用上面语言写的 发现是python&#xff0c;很容易想到ssti 密码随便输&#xff0c;发现没有回显 但是输入其他字符会报错 确定为ssti注入 开始构造payload&#xff0c; {{(lipsum|attr(‘global…

Git命令摘录

使用 Git 升级软件通常是指通过 Git 仓库获取软件的最新版本或更新代码。以下是详细的步骤和方法&#xff1a; 1. 克隆软件仓库 如果这是你第一次获取软件代码&#xff0c;可以使用 git clone 命令将远程仓库克隆到本地。 git clone <仓库地址> 例如&#xff1a; git cl…

2024年博客之星年度评选—创作影响力评审+主题文章创作评审目前排名(2024博客之星陪跑小分队助力2024博客之星创作者成长)

2024年博客之星年度评选—创作影响力评审主题文章创作评审目前排名 2024年博客之星主题文章创作评审文章得分公布&#xff01;2024年博客之星创作影响力评审2024年博客之星主题文章创作评审目前排名公布&#xff01; 【2024博客之星】恭喜完成✅主题创作的226位博主&#xff0…

unity 0基础自学2.1:unity 中button的各类状态

文章目录 1、Button的状态2、脚本中获取button的状态2.1 分析状态获取2.2 通过实现接口获取button的状态2.2.1 鼠标点击与释放2.2.2 高亮模式2.2.3 退出选中模式&#xff08;高亮状态&#xff09;2.2.4 选择模式selected2.2.5 退出选择模式 3、射线与UI交互设置3.1 Canvas中组件…

《C++ Primer》学习笔记(一)

第一部分&#xff1a;C基础 在C和C编程语言中&#xff0c;main函数必须返回int类型的值。这一要求自C标准的第一次规范&#xff08;C89&#xff0c;也叫ANSI C&#xff09;开始就已经明确规定了。std::endl和\n都用于插入换行符。std::endl除了换行&#xff0c;还会强制刷新输…

DedeBIZ系统审计小结

之前简单审计过DedeBIZ系统&#xff0c;网上还没有对这个系统的漏洞有过详尽的分析&#xff0c;于是重新审计并总结文章&#xff0c;记录下自己审计的过程。 https://github.com/DedeBIZ/DedeV6/archive/refs/tags/6.2.10.zip &#x1f4cc;DedeBIZ 系统并非基于 MVC 框架&…

C#快速排序QuickSort将递归算法修改为堆栈Stack非递归方式

我们知道,方法的调用是采用Stack的方式[后进先出:LIFO], 在DeepSeek中快速搜索C#快速排序, 搜索结果如图: 我们会发现是采用递归的方式 . 递归的优点: 简单粗暴,类似于直接写数学公式,因代码量较少,易于理解.递归与循环迭代的运行次数都是一致的 递归的缺点: 占用大量的内…

【DeepSeek × Postman】请求回复

新建一个集合 在 Postman 中创建一个测试集合 DeepSeek API Test&#xff0c;并创建一个关联的测试环境 DeepSeek API Env&#xff0c;同时定义两个变量 base_url 和 api_key 的步骤如下&#xff1a; 1. 创建测试集合 DeepSeek API Test 打开 Postman。点击左侧导航栏中的 Co…

[免费]Springboot+Vue医疗(医院)挂号管理系统【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的SpringbootVue医疗(医院)挂号管理系统&#xff0c;分享下哈。 项目视频演示 【免费】SpringBootVue医疗(医院)挂号管理系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 在如今社会上&#xff0c;关于信息上…

计算机毕业设计PySpark+hive招聘推荐系统 职位用户画像推荐系统 招聘数据分析 招聘爬虫 数据仓库 Django Vue.js Hadoop

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

Jmeter+Influxdb+Grafana平台监控性能测试过程

一、Jmeter自带插件监控 下载地址&#xff1a;https://jmeter-plugins.org/install/Install/ 安装&#xff1a;下载后文件为jmeter-plugins-manager-1.3.jar&#xff0c;将其放入jmeter安装目录下的lib/ext目录&#xff0c;然后重启jmeter&#xff0c;即可。 启动Jmeter&…

ROACH

End-to-End Urban Driving by Imitating a Reinforcement Learning Coach CARLA-Roach ICCV‘21论文&#xff1a;模仿一个强化学习教练的端到端城市驾驶 文章目录 Roach输入BEV语义分割图像测量向量 Roach输出训练策略网络价值网络 具体实现由 Roach 监督的模仿学习&#xff08…

机械臂运动学笔记(一):正向运动学

正向运动学指的是通过相邻关节间的转动和移动坐标&#xff0c;将末端的坐标计算出来。 反向运动学指的是已知机械臂末端的坐标&#xff0c;反算每个关节可能的转动和移动参数。 参考资料&#xff1a;4.机械臂几何法与DH表示法_哔哩哔哩_bilibili 一.任意连杆连接的变量定义&a…

【DuodooBMS】给PDF附件加“受控”水印的完整Python实现

给PDF附件加“受控”水印的完整Python实现 功能需求 在实际工作中&#xff0c;许多文件需要添加水印以标识其状态&#xff0c;例如“受控”“机密”等。对于PDF文件&#xff0c;添加水印不仅可以增强文件的可识别性&#xff0c;还可以防止未经授权的使用。本代码的功能需求是…