Java设计模式之职责链模式详解


一、职责链模式核心思想

核心目标将请求的发送者与接收者解耦,使多个对象都有机会处理请求。这些处理者形成链式结构,请求沿链传递直到被处理或到达链尾,如政府审批层层上报机制。


二、职责链模式类图(Mermaid)

组合
«abstract»
Handler
-nextHandler: Handler
+setNext(Handler)
+handleRequest(int level)
ConcreteHandlerA
+handleRequest(int level)
ConcreteHandlerB
+handleRequest(int level)
Client

三、代码实现示例

1. 请假审批场景

// 抽象处理者
abstract class Approver {protected Approver nextApprover;protected String name;protected int maxApproveDays;public Approver(String name, int maxDays) {this.name = name;this.maxApproveDays = maxDays;}public Approver setNext(Approver next) {this.nextApprover = next;return this;}public void processRequest(LeaveRequest request) {if (request.getDays() <= maxApproveDays) {System.out.printf("%s 审批了 %d 天请假(原因:%s)\n", name, request.getDays(), request.getReason());} else if (nextApprover != null) {nextApprover.processRequest(request);} else {System.out.println("请假天数过长,无人可审批!");}}
}// 具体处理者
class Manager extends Approver {public Manager() { super("张经理", 3); }
}class Director extends Approver {public Director() { super("王总监", 7); }
}class CEO extends Approver {public CEO() { super("李总裁", 15); }
}// 请求对象
class LeaveRequest {private int days;private String reason;// 构造方法、getter省略
}// 客户端调用
Approver chain = new Manager().setNext(new Director()).setNext(new CEO());chain.processRequest(new LeaveRequest(5, "看病"));  
// 输出:王总监 审批了 5 天请假(原因:看病)
chain.processRequest(new LeaveRequest(20, "旅游")); 
// 输出:请假天数过长,无人可审批!

四、模式优缺点分析

✅ 优势

  • 解耦请求与处理:发送者无需知道具体处理者
  • 动态调整责任链:可运行时修改链结构
  • 符合开闭原则:新增处理者无需修改已有代码

❌ 缺点

  • 请求可能未被处理:需要设计默认处理逻辑
  • 性能影响:长链可能导致请求处理延迟
  • 调试困难:请求传递路径不易追踪

五、典型应用场景

  1. 多级审批系统:OA系统中的请假/报销审批
  2. 异常处理机制:Spring MVC的异常处理链
  3. 过滤器/拦截器链:Servlet Filter、Spring Interceptor
  4. 日志处理系统:不同级别日志(DEBUG/INFO/ERROR)分发
  5. 游戏事件处理:UI元素的事件冒泡机制

六、Mermaid序列图(请求传递流程)

Client HandlerA HandlerB HandlerC processRequest() 判断能否处理 处理完成 processRequest() 判断能否处理 处理完成 processRequest() 处理结果 alt [可处理] [不可处理] alt [可处理] [不可处理] Client HandlerA HandlerB HandlerC

七、职责链模式 vs 其他模式

对比模式核心区别
装饰器模式层层增强功能,所有处理者必须执行
命令模式封装请求为对象,关注请求生命周期
状态模式状态转换改变行为,处理者内部切换

八、高级应用技巧

1. 组合模式实现树形责任链

包含
CompositeHandler
-children: List
+add(Handler)
+handleRequest()
Handler

2. 中断链式传递

public void processRequest(Request req) {if (canHandle(req)) {// 处理逻辑return;  // 中断传递}if (next != null) next.processRequest(req);
}

九、Spring框架应用案例

Spring Security过滤器链

FilterChainProxy
-filterChains: List
+doFilter()
DefaultSecurityFilterChain
-filters: List
«interface»
Filter
+doFilter()

十、常见问题解答

Q1:如何避免循环链?

  • 设置最大传递深度:计数器限制链长度
  • 使用DAG验证:构建链时检查环状结构
  • 单元测试覆盖:验证链式调用路径

Q2:如何处理异步责任链?

  • 使用CompletableFuture:Java 8+的异步编程
public CompletableFuture<Void> asyncProcess(Request req) {return CompletableFuture.runAsync(() -> process(req));
}

Q3:如何调试责任链?

  • 添加Trace ID:为请求添加唯一标识
  • 日志记录器:每个处理者记录处理状态
public void process(Request req) {log.debug("Handler {} 开始处理请求 {}", name, req.getId());// 处理逻辑
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决WPF短暂的白色闪烁(白色闪屏)

在 WPF 应用程序启动时出现 短暂的白色闪烁&#xff08;白色闪屏&#xff09;&#xff0c;通常是由于以下原因导致的&#xff1a; 主要原因 WPF 默认窗口背景是白色&#xff0c;在加载 UI 之前会短暂显示白色背景。 解决方案 设置窗口背景为透明或黑色&#xff08;推荐&…

《Python基础》第1期:人生苦短,我用Python

介绍 Python 在英语中是蟒蛇的意思&#xff0c;它的 logo 也是两条蟒蛇缠绕在一起。 然而 Python 和蟒蛇实际上没有半点关系。 Python 是由荷兰程序员 Guido van Rossum&#xff08;因为其名字的前三个字母“gui”是中文“龟”的拼音&#xff0c;所以江湖人称“龟叔”&#x…

DiT、 U-Net 与自回归模型的优势

DiT 相对于 U-Net 的优势 全局自注意力 vs. 局部卷积 U-Net 依赖卷积和池化/上采样来逐层扩大感受野&#xff0c;捕捉全局信息需要堆叠很多层或借助跳跃连接&#xff08;skip connections&#xff09;。DiT 在每个分辨率阶段都用 Transformer 模块&#xff08;多头自注意力 ML…

怎么查找idea插件的下载位置,并更改

长期使用 IntelliJ IDEA 时&#xff0c;默认存储在 C 盘的配置文件会持续生成大量缓存和日志文件&#xff0c;可能导致系统盘空间不足。通过修改默认配置文件存储位置&#xff0c;可以有效释放 C 盘空间并提升系统性能。 1&#xff0c;先找到自己idea的下载目录&#xff0c;再打…

IoT/HCIP实验-1/物联网开发平台实验Part2(HCIP-IoT实验手册版)

文章目录 概述产品和设备实例的产品和设备产品和设备的关联单个产品有多个设备为产品创建多个设备产品模型和物模型设备影子&#xff08;远程代理&#xff09; 新建产品模型定义编解码插件开发编解码插件工作原理消息类型与二进制码流添加消息&#xff08;数据上报消息&#xf…

15.进程间通信(一)

一、进程间通信介绍 进程间通信目的&#xff1a; 数据传输&#xff1a;一个进程需要将它的数据发送给另⼀个进程 资源共享&#xff1a;多个进程之间共享同样的资源。 通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它&#xff08;它们&#xf…

05-jenkins学习之旅-vue前项目部署实践

1、创建被管理项目 2、构建流程说明 jenkins其实就是将服务部署拆分成了&#xff1a; 1、拉取代码(git) 2、打包编译(npm install) 3、自定义脚本(dist复制、执行启动脚本) 4、部署成功后的一些通知等 3、demo配置 3.1、General 3.2 源码管理 添加用户名密码方式如下图 3.2…

服务器中分布式存储数据技术都包含哪些内容?

随着大数据时代的到来&#xff0c;企业和组织对于服务器的存储要求也在不断地增高&#xff0c;传统的存储架构已经无法满足一些大规模的数据存储和处理需求&#xff0c;分布式存储技术应运而生&#xff0c;成为了大数据存储的重要基础设施&#xff0c;下面&#xff0c;就来介绍…

从比分滚动到数据革命:体育数据如何重构我们的观赛体验?

当凌晨三点的欧冠决赛与闹钟冲突时&#xff0c;当世界杯小组赛因时差难以全程跟进时&#xff0c;当代体育迷早已不再依赖电视直播 —— 打开手机里的比分网&#xff0c;实时跳动的体育大数据正构建着全新的观赛宇宙。这些曾经被视为 "辅助工具" 的平台&#xff0c;如…

vue2使用element中多选组件el-checkbox-group,数据与UI更新不同步

问题描述 使用element多选checkbox组件&#xff0c;点击勾选取消勾选&#xff0c;视图未变化&#xff0c;再次点击表单其他元素&#xff0c;多选组件勾选状态发生变化&#xff0c;视图和数据未同步 第一次尝试&#xff1a;再el-checkbox-group多选父组件上增加点击事件&…

CodeTop之LRU缓存

题目链接 146. LRU 缓存 - 力扣&#xff08;LeetCode&#xff09; 题目解析 算法原理 我们使用双向链表哈希表的形式来模拟缓存机制 首先我们要自己实现一个双链表, 自己写一个内部类, 这个内部类记录了key,value,prev,next(前驱和后继), 后续我们就通过这个内部类来构造双…

PyQt学习系列11-综合项目:多语言文件管理器

PyQt学习系列笔记&#xff08;Python Qt框架&#xff09; 第十一课&#xff1a;综合项目 - 多语言文件管理器 &#xff08;原课程规划中的第十五课&#xff0c;按用户要求调整为第十一课&#xff09; 课程目标 综合运用PyQt框架开发一个支持多语言的文件管理器实现以下核心功…

【Ubuntu修改串口延时(Latency Timer)为1毫秒(设备拔插或系统重启后自动生效)】

Ubuntu修改串口延时Latency Timer为1毫秒-设备拔插或系统重启后自动生效 在Ubuntu系统中&#xff0c;串口设备的延时参数(latency_timer)可以通过udev规则永久修改。以下是完整步骤&#xff1a; 创建udev规则文件 sudo vim /etc/udev/rules.d/99-ftdi-low-latency.rules添加以…

OpenCV CUDA模块图像处理------颜色空间处理之GPU 上交换图像的通道顺序函数swapChannels()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数用于在 GPU 上交换图像的通道顺序&#xff08;例如将 BGR 图像转为 RGB&#xff09;。 它适用于多通道图像&#xff08;如 3 通道或 4 通道…

Linux Ubuntu24.04配置安装MySQL8.4.5高可用集群主从复制!

MySQL 主从复制&#xff08;Replication&#xff09;是实现数据高可用、读写分离及异地容灾的核心机制之一。主库写、从库读&#xff0c;提升并发能力&#xff1b;读写分离&#xff0c;减轻主库压力。 本地 windows 系统有一个Linux Ubuntu子系统&#xff0c;版本为Ubuntu 24.…

R基于逻辑回归模型实现心脏病检测及SHAP值解释项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后关注获取。 1.项目背景 心血管疾病是全球范围内导致死亡的主要原因之一&#xff0c;每年有数百万人因此失去生命。在众多的…

嵌入式学习笔记 -函数嵌套时以及异常响应时,LR使用的具体过程

函数嵌套时以及异常响应时&#xff0c;寄存器LR的作用存在显著区别&#xff0c;理解这个问题对于理解freeRTOS底层代码的实现大有帮助&#xff0c;具体使用过程如下&#xff1a; 一 函数嵌套时的LR使用的具体过程 在ARM架构(特别是M0处理器)中&#xff0c;函数嵌套调用时LR(L…

Java String函数的使用

文章目录 String字符串比较字符串查找转化字符串替换字符串拆分字符串截取&#xff08;常用&#xff09;字符串的不可变性 String str本来是字符串常量的引用&#xff0c;应该打印地址&#xff0c;但是编译器重写了toString方法&#xff0c;所以打印hello String 的构造方法 …

Oracle 11G RAC重启系统异常

vmware安装centos7环境部署Oracle RAC (11.2.0.4) 部署时所有资源情况都是正常的&#xff0c;关机重启虚拟机后集群资源状态异常&#xff0c;请教CSDN大佬 – 部署规划 域名地址备注rac16192.168.31.16rac17192.168.31.17rac16vip192.168.31.26viprac17vip192.168.31.27vip…

吉林省CCPC与全国邀请赛(东北地区赛)游记

总述&#xff1a; 本次赛段共获得一银&#xff08;吉林省赛&#xff09;、一铜&#xff08;东北地区赛&#xff09;、一铁&#xff08;全国邀请赛的成绩&#xff09;。总体成绩跟校内赛的情况相比队伍状态与发挥水准都有提升&#xff09;&#xff0c;但也体现出很多不足&#x…