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

[java] 23种设计模式之责任链模式

1.1例子

公司请假系统,业务逻辑如下:
不超过3天的,组长审批
超过3天且小于7天的,总监审批
超过7天且小于15天的,部长审批
超过15天,前端直接拒绝,不会进入审批流程(违反了公司的请假规定)
底层小职员请假,直接去OA系统填写请假申请,生成请假工单
系统会根据请假天数,将请假工单派发给对应的审批人

1.2 考虑使用责任链模式

以请假审批系统为例,组长 → \rightarrow→ 总监 → \rightarrow→ 部长形成了一条链
职员提交请假申请后,请求会沿着这条链传递,直到有对象可以处理它。
一个5天的请假申请,先到达组长处;
组长无权限审批,传递请求到自己的上级(总监);
总监有权限审批,于是同意了该请假申请
作为请求的发送者,职员无需关心最终由谁审批,只需要提交请求即可
这样的设计模式,就是责任链模式(Chain of Responsibility)


                        
1.3 自己理解

一个请求可能需要由不同的handler独立处理,或者需要多个handler同时处理
如果按照常规的编程模式,可能需要繁杂的if-else去实现
将handler通过next引用形成一条责任链,请求发送者只需要发送请求到责任链
请求会在责任链中传递,直到被对应的handler处理(一个或多个)或者无法被处理
这样的话,请求发送者无需关心handler的处理逻辑和请求的传递过程,实现了请求的发送者和处理者的解耦。

1.4 实现一个请假系统

第一步:创建抽象处理者

public abstract class Handler {private Handler next;public void setNext(Handler next) {this.next = next;}public Handler getNext() {return next;}public abstract void handleRequest(String name, int days);
}

第二步:创建组长、总监、部长三个具体处理者,实现具体的处理逻辑

public class PMHandler extends Handler {@Overridepublic void handleRequest(String name, int days) {if (days <= 3) {System.out.println(name + ",组长已经同意您的请假审批!");} else {if (getNext() != null) {getNext().handleRequest(name, days);} else {System.out.println("请假天数太多,申请被驳回!");}}}
}public class DirectorHandler extends Handler {@Overridepublic void handleRequest(String name, int days) {if (days <= 7) {System.out.println(name + ",中心总监已经同意您的请假审批");} else {if (getNext() != null) {getNext().handleRequest(name, days);} else {System.out.println("请假天数太多,申请被驳回!");}}}
}public class MinisterHandler extends Handler {@Overridepublic void handleRequest(String name, int days) {if (days <= 15) {System.out.println(name + ",部长已经同意您的请假审批");} else {if (getNext() != null) {getNext().handleRequest(name, days);} else {System.out.println("请假天数太多,申请被驳回!");}}}
}

第三步:创建Clinet类,在类中创建并使用责任链(向责任链传递请求)

public class OASystem {public static void main(String[] args) {// 创建具体处理者Handler pm = new PMHandler();Handler director = new DirectorHandler();Handler minister = new MinisterHandler();// 构建责任链pm.setNext(director);director.setNext(minister);// 使用责任链pm.handleRequest("张三", 5);}
}

最终的执行结果如下:

相关文章:

  • 大端序、小端序和MSB、LSB
  • 【数据结构】知识点一:线性表之顺序表
  • 多线程系列(十五) -常用并发工具类详解
  • 封装方法2
  • 计算机网络-网络安全(二)
  • 基于Spring Boot+ Vue的房屋租赁系统
  • LVS集群(Linux Virtual server)相关介绍及LVS的NAT模式部署
  • GPT的历史
  • 【设计模式】(二)设计模式六大设计原则
  • LeetCode 热题 100 | 图论(二)
  • 【粉丝福利】一本书讲透ChatGPT,实现从理论到实践的跨越!大模型技术工程师必读
  • 线性代数笔记11--矩阵空间、秩1矩阵
  • 数据库-第四/五章 数据库安全性和完整性【期末复习|考研复习】
  • [Vulnhub]靶场 Web Machine(N7)
  • 【CSP试题回顾】202209-2-何以包邮?
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • CNN 在图像分割中的简史:从 R-CNN 到 Mask R-CNN
  • in typeof instanceof ===这些运算符有什么作用
  • JavaScript DOM 10 - 滚动
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • Puppeteer:浏览器控制器
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • win10下安装mysql5.7
  • 前嗅ForeSpider采集配置界面介绍
  • 入口文件开始,分析Vue源码实现
  • 突破自己的技术思维
  • 小而合理的前端理论:rscss和rsjs
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 06-01 点餐小程序前台界面搭建
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 移动端高清、多屏适配方案
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ​Python 3 新特性:类型注解
  • # C++之functional库用法整理
  • #14vue3生成表单并跳转到外部地址的方式
  • #Spring-boot高级
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (一)UDP基本编程步骤
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • ... 是什么 ?... 有什么用处?
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .Net - 类的介绍
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .NET 的程序集加载上下文
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .NET企业级应用架构设计系列之开场白