当前位置: 首页 > news >正文

Java 23 种设计模式:从踩坑到精通 | 番外:责任链模式 —— 物流审批流程实战

Java 23 种设计模式:从踩坑到精通 | 番外:责任链模式 —— 物流审批流程实战

摘要:责任链模式将请求的发送者与接收者解耦,让多个对象都有机会处理请求,通过将对象串成一条链,请求沿链自动传递,直到被某个对象处理。本文结合物流公司请假审批系统的场景,完整展示如何用责任链模式实现分级审批,支持动态调整审批链,并与命令模式深度对比,帮你掌握“请求传递,各司其职”的设计精髓。

🗺️本文阅读地图(3 分钟速览)

  • 为什么审批流程的 if-else 一定会炸?
  • ✅ 责任链核心角色:抽象处理者、具体处理者
  • 手写请假审批链:组长→经理→HR,自动传递
  • 🚀 动态调整链:临时跳过某一级审批
  • 🎤 面试必问:“责任链模式和命令模式有什么区别?”

📖《Java 23 种设计模式:从踩坑到精通》
开篇:系列介绍与目录 | 正篇:责任链模式 Chain of Responsibility —— 请求流转,审批流程的本质 |当前:番外 · 责任链模式 × 物流审批流程
🔗 返回系列总目录

1. 物流审批流程的痛点

在物流公司,请假审批需要根据不同天数由不同级别审批:3 天以内由直属领导审批,3 到 7 天由部门经理审批,7 到 30 天由 HR 总监审批,超过 30 天直接拒绝。如果把这个逻辑写成if-else

if(days<=3){teamLeader.approve();}elseif(days<=7){manager.approve();}elseif(days<=30){hr.approve();}else{reject();}

这种写法将审批规则死死绑在代码中。当审批流程变化(如增加财务审批、临时授权某人越级审批)时,必须修改核心代码。更糟糕的是,如果审批节点需要动态调整(如经理出差时临时跳过),静态if-else完全无法应对。

责任链模式的解决思路:将各个审批节点串联成一条链,请求从链头开始自动传递,每个节点只判断“我能不能处理”,能处理则处理,不能处理则传给下一个节点。链的结构可在运行时动态调整,完全符合开闭原则。

1.1 你的场景该不该用责任链?

判断标准是 → 用责任链否 → 用其他方式
有多个对象可以处理同一请求,处理器动态确定
处理器顺序需要灵活调整,甚至运行时动态改变
希望请求自动传递,无需客户端指定由谁处理
处理逻辑非常简单,且处理器固定不变直接调用即可

2. 责任链模式 UML(物流请假审批场景)


3. 完整源码实现

3.1 请求对象:请假申请 (LeaveRequest)

/** * 请假请求对象:封装请求数据 */publicclassLeaveRequest{privateStringemployeeName;privateintdays;privateStringreason;publicLeaveRequest(StringemployeeName,intdays,Stringreason){this.employeeName=employeeName;this.days=days;this.reason=reason;}publicStringgetEmployeeName(){returnemployeeName;}publicintgetDays(){returndays;}publicStringgetReason(){returnreason;}@OverridepublicStringtoString(){returnString.format("%s申请请假%d天,原因:%s",employeeName,days,reason);}}

💬白话:请假请求就像一个“工单”,上面写明了谁请假、请几天、什么原因。它不关心谁来审批,只管带着数据在链上跑。

3.2 抽象处理者:审批者 (Approver)

/** * 抽象审批者:定义处理请求的统一接口 */publicabstractclassApprover{protectedApprovernextApprover;protectedStringname;publicApprover(Stringname){this.name=name;}/** * 设置下一个审批者,支持链式调用 */publicApproversetNext(Approvernext){this.nextApprover=next;returnnext;}/** * 处理请求 */publicvoidhandleRequest(LeaveRequestrequest){if(canApprove(request.getDays())){approve(request);}elseif(nextApprover!=null){System.out.printf(" ⏩ %s 无权审批%d天,转交给 %s\n",name,request.getDays(),nextApprover.name);nextApprover.handleRequest(request);}else{reject(request);}}protectedabstractbooleancanApprove(intdays);protectedvoidapprove(LeaveRequestrequest){System.out.printf(" ✅ %s 批准了:%s\n",name,request);}protectedvoidreject(LeaveRequestrequest){System.out.printf(" ❌ %s 拒绝了:%s(超出最大审批权限)\n",name,request);}}

💬白话handleRequest是责任链的核心——先看自己能不能批,能就批;不能就甩给下一个。setNext返回下一个节点,支持链式拼接,像“链表”一样把审批者串起来。

3.3 具体处理者:直属领导 (TeamLeader)

publicclassTeamLeaderextendsApprover{publicTeamLeader(Stringname){super(name);}@OverrideprotectedbooleancanApprove(intdays){returndays<=3;}}

3.4 具体处理者:部门经理 (DepartmentManager)

publicclassDepartmentManagerextendsApprover{publicDepartmentManager(Stringname){super(name);}@OverrideprotectedbooleancanApprove(intdays){returndays<=7;}}

3.5 具体处理者:HR 总监 (HRDirector)

publicclassHRDirectorextendsApprover{publicHRDirector(Stringname){super(name);}@OverrideprotectedbooleancanApprove(intdays){returndays<=30;}}

3.6 客户端测试

publicclassClient{publicstaticvoidmain(String[]args){System.out.println("=== 物流公司请假审批系统(责任链模式)===\n");// 1. 构建责任链:直属领导 → 部门经理 → HR总监ApproverteamLeader=newTeamLeader("张组长");Approvermanager=newDepartmentManager("李经理");Approverhr=newHRDirector("王总监");teamLeader.setNext(manager).setNext(hr);// 链式拼接// 2. 测试不同天数LeaveRequest[]requests={newLeaveRequest("小赵",1,"感冒发烧"),newLeaveRequest("小钱",5,"回家探亲"),newLeaveRequest("小孙",15,"婚假"),newLeaveRequest("小李",45,"长期进修")};for(LeaveRequestrequest:requests){System.out.println("【申请】"+request);teamLeader.handleRequest(request);System.out.println();}// 3. 动态调整:经理出差,跳过经理直接到 HRSystem.out.println("=== 临时授权:跳过经理 ===");Approvertl=newTeamLeader("张组长");tl.setNext(newHRDirector("王总监"));tl.handleRequest(newLeaveRequest("小周",6,"家庭事务"));}}

💬白话setNext(manager).setNext(hr)是链式拼接的标准写法。场景 3 中,teamLeader直接连到hr,跳过了经理——这就是责任链在运行时的灵活性。

4. 运行结果

=== 物流公司请假审批系统(责任链模式)=== 【申请】小赵申请请假1天,原因:感冒发烧 ✅ 张组长 批准了:小赵申请请假1天,原因:感冒发烧 【申请】小钱申请请假5天,原因:回家探亲 ⏩ 张组长 无权审批5天,转交给 李经理 ✅ 李经理 批准了:小钱申请请假5天,原因:回家探亲 【申请】小孙申请请假15天,原因:婚假 ⏩ 张组长 无权审批15天,转交给 李经理 ⏩ 李经理 无权审批15天,转交给 王总监 ✅ 王总监 批准了:小孙申请请假15天,原因:婚假 【申请】小李申请请假45天,原因:长期进修 ⏩ 张组长 无权审批45天,转交给 李经理 ⏩ 李经理 无权审批45天,转交给 王总监 ❌ 王总监 拒绝了:小李申请请假45天,原因:长期进修(超出最大审批权限) === 临时授权:跳过经理 === ⏩ 张组长 无权审批6天,转交给 王总监 ✅ 王总监 批准了:小周申请请假6天,原因:家庭事务

5. 核心角色回顾

角色职责对应代码
Handler定义处理请求的接口,持有下一个处理者引用Approver
ConcreteHandler处理自己能处理的请求,否则传给下一个TeamLeader/DepartmentManager/HRDirector

6. 责任链模式 vs 命令模式

对比项责任链模式命令模式
意图请求沿链传递,直到被处理将请求封装为对象,支持撤销/队列
请求与处理者关系一个请求可被多个处理者“过目”一个命令对应一个接收者
典型应用审批流程、Filter 链遥控器、宏命令、线程池

💡一句话记忆:责任链是“传话接力”——谁能处理谁就留下;命令模式是“指令封装”——执行者拿到指令直接干活,不会传给下一个人。

7. 责任链模式的优缺点

优点缺点
请求发送者与处理者解耦,灵活扩展链太长时性能有影响
可动态调整链的结构调试不便,需追踪整条链
符合单一职责和开闭原则请求可能到达链尾仍未被处理

8. 六大设计原则体现

原则体现
单一职责每个审批者只负责自己权限范围内的审批
开闭原则新增审批级别只需加新类,不改原有代码
里氏替换所有审批者都可替换抽象Approver
依赖倒置客户端依赖抽象Approver,不依赖具体审批者
接口隔离Approver方法精简,只定义处理与设置下一个
迪米特法则请求只与链头交互,不知道链的结构

附 责任链模式 UML 源码(物流请假审批场景)

@startuml title Java 23 种设计模式:从踩坑到精通 footer 折哥 | 智能物流与Java实战 ' 1. 全局样式配置 skinparam backgroundColor #FEFEFE skinparam shadowing false skinparam classBorderColor #333333 skinparam classFontColor #1A1A1A skinparam classFontSize 14 skinparam noteFontSize 12 skinparam noteFontColor #555555 skinparam arrowColor #555555 skinparam classBackgroundColor #F9F9F9 skinparam interface { BackgroundColor #E8F5E9 BorderColor #2E7D32 } ' 2. 请求对象 class LeaveRequest { - employeeName : String - days : int - reason : String + getDays() : int + getEmployeeName() : String } note right of LeaveRequest <b>请假请求</b> -- 封装请求数据 包含员工姓名、天数、原因 end note ' 3. 抽象处理者 abstract class Approver { - nextApprover : Approver - name : String + handleRequest(request : LeaveRequest) : void + setNext(next : Approver) : Approver # canApprove(days : int) : boolean } note right of Approver <b>抽象处理者</b> -- 定义处理请求的接口 持有下一个处理者的引用 子类实现具体的审批逻辑 end note ' 4. 具体处理者:直属领导 class TeamLeader extends Approver { + handleRequest(request : LeaveRequest) : void # canApprove(days : int) : boolean } note right of TeamLeader <b>直属领导</b> -- 审批权限:≤ 3天 超过3天则转交给上级 审批通过后流程结束 end note ' 5. 具体处理者:部门经理 class DepartmentManager extends Approver { + handleRequest(request : LeaveRequest) : void # canApprove(days : int) : boolean } note right of DepartmentManager <b>部门经理</b> -- 审批权限:≤ 7天 超过7天则转交给HR 审批通过后流程结束 end note ' 6. 具体处理者:HR class HRDirector extends Approver { + handleRequest(request : LeaveRequest) : void # canApprove(days : int) : boolean } note bottom of HRDirector <b>HR总监</b> -- 审批权限:≤ 30天 作为最终兜底处理者 超过30天则拒绝 end note ' 7. 关系连线 LeaveRequest <-- Approver : 处理 Approver o--> Approver : next 指向下一个 TeamLeader --|> Approver : 继承 DepartmentManager --|> Approver : 继承 HRDirector --|> Approver : 继承 @enduml

🧭 《Java 23 种设计模式:从踩坑到精通》快速导航

  • 开篇:系列介绍与目录
  • 正篇:责任链模式 Chain of Responsibility —— 请求流转,审批流程的本质
  • 当前:番外 · 责任链模式 × 物流审批流程(你在这里)
  • 创建型模式汇总
  • 结构型模式汇总
  • 行为型模式汇总

🔔 关注《Java 23 种设计模式:从踩坑到精通》,用 25 篇文章彻底吃透设计模式。
📦福利预告:全系列代码及 UML 源码将在完结时统一打包开放,点击「关注」「收藏」第一时间获取。

📌 除了设计模式,我也在深挖智能物流实战(WMS、托盘调度、机器学习落地)。欢迎点击头像,看看专栏 《出版社物流WMS智能调度实战》、《电商多平台电子面单对接实战》。技术相通,思路可鉴。

http://www.jsqmd.com/news/1303408/

相关文章:

  • ClickHouse版本管理深度实战:4步构建零风险升级与回滚体系
  • LLM推理模型工作机制与优化技术详解
  • 【Kimi图表解读终极指南】:20年数据可视化专家亲授5大避坑法则与3类高频误读场景破解术
  • 爱回收深度测评|手机回收哪个平台划算?四家主流渠道实测对比 - 甄选测评馆
  • llms.txt技术方案:解决大语言模型网站内容理解的架构化指南
  • 药板铝泊板缺陷检测数据集2375张VOC+YOLO格式
  • 绝区零全自动游戏助手:一键解放双手的智能自动化工具
  • 如何快速提取视频字幕:3分钟完成硬字幕转换的完整指南
  • 北京买狗必避三大深坑!这三家实体门店远离星期狗套路 - 北京同城宠物基地
  • 构建个人漫画云图书馆:Suwayomi-Server完全指南
  • 【实战指南】构建本地AI语音合成系统:开发者的高效解决方案
  • Open Generative AI:打破AI创作限制的开源解决方案
  • 字体改一改、间距调一调不算侵权?商标侵权判定标准!
  • MPV PlayKit:从技术门槛到专业级播放体验的完整解决方案
  • codex 安装脚本分析
  • 大型语言模型内部策略架构与自底向上强化学习实践
  • GoReSym逆向分析:三步破解Go二进制符号恢复难题的完整指南
  • SWE-bench实战指南:构建语言模型代码修复能力的评估框架
  • 如何用Python-SoundDevice轻松玩转音频录制与播放
  • 今天干了一件大事!
  • 5G+AI语音质检系统上线实录:单日处理2800万通电话,准确率99.2%背后的3层模型协同架构
  • 豪宅智能化的质感密码:2026年定制品牌能力深度解析
  • DLSS版本管理完全指南:3分钟掌握游戏性能优化技巧
  • 如何用AI提升图像生成质量?Z-Image-Engineer V6的智能解决方案
  • AI做在线工具网站:3天快速上线MVP的5个关键决策点(附2024最新技术栈清单)
  • 短视频直播商城系统变现全攻略:私域变现新玩法与短视频社交APP源码选型 - 壹软科技
  • 2026最新粤港澳商务跨境包车口碑榜 4家服务商服务对比 - 甄选测评馆
  • Speech-to-Speech:用开源模型构建本地语音智能体的完整指南
  • 基于HSV颜色空间的农业杂草识别系统设计与实现
  • [Android ] µTorrent 汉化高级版 -磁力种子资源搜索+下载的工具