java设计模式之职责链模式
基本介绍
- 职责链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式对请求的发送者和接收者进行解耦。
- 职责链模式 又叫责任链模式,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求。那么它会把相同的请求传给下一个接收者。依次类推。
- 这种类型的设计模式属于行为型模式。
引入需求
采购员采购物品
- 如果金额小于等于5000,由教学主任审批
- 如果金额小于等于10000,由院长审批
- 如果金额小于等于30000,由副校长审批
- 如果金额超过3000以上,由校长审批
思路分析
传统方式:接收到一个采购请求后,根据采购金额来调用对应的审批人完成审批。
传统方式问题分析:
客户端会使用分支判断(if else / switch)来对不同的采购请求处理。就会产生以下问题:
- 如果各个级别的人员审批金额发生变化,在客户端也需要变化。
- 客户端必须明确知道有多少审批级别。
- 不利于代码扩展维护。
职责链模式解决类图:

代码如下:
public class PurchaseRequest {private int type = 0; //请求类型private float price = 0.0f; //请求金额private int id = 0;//构造器public PurchaseRequest(int type, float price, int id) {this.type = type;this.price = price;this.id = id;}public int getType() {return type;}public float getPrice() {return price;}public int getId() {return id;}
}public abstract class Approver {Approver approver; //下一个处理者String name; // 名字public Approver(String name) {this.name = name;}//下一个处理者public void setApprover(Approver approver) {this.approver = approver;}//处理审批请求的方法,得到一个请求, 处理是子类完成,因此该方法做成抽象public abstract void processRequest(PurchaseRequest purchaseRequest);}
public class DepartmentApprover extends Approver {public DepartmentApprover(String name) {// TODO Auto-generated constructor stubsuper(name);}@Overridepublic void processRequest(PurchaseRequest purchaseRequest) {// TODO Auto-generated method stubif(purchaseRequest.getPrice() <= 5000) {System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");}else {approver.processRequest(purchaseRequest);}}
}
public class CollegeApprover extends Approver {public CollegeApprover(String name) {// TODO Auto-generated constructor stubsuper(name);}@Overridepublic void processRequest(PurchaseRequest purchaseRequest) {// TODO Auto-generated method stubif(purchaseRequest.getPrice() < 5000 && purchaseRequest.getPrice() <= 10000) {System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");}else {approver.processRequest(purchaseRequest);}}
}
public class ViceSchoolMasterApprover extends Approver {public ViceSchoolMasterApprover(String name) {// TODO Auto-generated constructor stubsuper(name);}@Overridepublic void processRequest(PurchaseRequest purchaseRequest) {// TODO Auto-generated method stubif(purchaseRequest.getPrice() < 10000 && purchaseRequest.getPrice() <= 30000) {System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");}else {approver.processRequest(purchaseRequest);}}
}
public class SchoolMasterApprover extends Approver {public SchoolMasterApprover(String name) {// TODO Auto-generated constructor stubsuper(name);}@Overridepublic void processRequest(PurchaseRequest purchaseRequest) {// TODO Auto-generated method stubif(purchaseRequest.getPrice() > 30000) {System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");}else {approver.processRequest(purchaseRequest);}}
}public static void main(String[] args) {// TODO Auto-generated method stub//创建一个请求PurchaseRequest purchaseRequest = new PurchaseRequest(1, 100000, 1);//创建相关的审批人DepartmentApprover departmentApprover = new DepartmentApprover("张主任");CollegeApprover collegeApprover = new CollegeApprover("李院长");ViceSchoolMasterApprover viceSchoolMasterApprover = new ViceSchoolMasterApprover("王副校");SchoolMasterApprover schoolMasterApprover = new SchoolMasterApprover("佟校长");//需要将各个审批级别的下一个设置好 (处理人构成环形: )departmentApprover.setApprover(collegeApprover);collegeApprover.setApprover(viceSchoolMasterApprover);viceSchoolMasterApprover.setApprover(schoolMasterApprover);schoolMasterApprover.setApprover(departmentApprover);departmentApprover.processRequest(purchaseRequest);}
注意事项和细节
- 将请求和处理分开,实现解耦,提高系统的灵活性。
- 简化了对象,使对象不需要知道链的结构。
- 性能会收到影响,特别是链比较长的时候,因此需要控制链中最大节点的数量,一般通过Handler中设置一个最大节点数量,在setNext()方法中判断是否已经超过与阈值,超过则不允许该链建立,避免出现超长链无意识的破坏系统性能。
- 调试不方便,采用了类似递归的方式,调试时逻辑可能比较复杂。
最佳应用场景:有多个对象可以处理同一个请求时,比如:多级请求,请假。加薪等审批流程。 java web中Tomcat对Encoding的处理,拦截器。
相关文章:
java设计模式之职责链模式
基本介绍 职责链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式对请求的发送者和接收者进行解耦。职责链模式 又叫责任链模式,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求。那…...
连不上网的解决办法集--持续更新
连不上网的解决办法集–持续更新 1、有网卡,但网卡驱动失效 背景:有网络驱动但是依旧连不上网,只有inteV6有值,inte 没有值(正常应该有个ipv4的信息) 判断原因:可能是之前格式化磁盘驱动的时…...
Unity之PUN2插件实现多人联机射击游戏
目录 📖一、准备工作 📺二、UI界面处理 📱2.1 登录UI并连接PUN2服务器 📱2.2 游戏大厅界面UI 📱2.3 创建房间UI 📱2.4 进入房间UI 📱2.5 玩家准备状态 📱2.6 加载战斗场景…...
72_Pandas.DataFrame保存并读取带pickle的系列(to_pickle、read_pickle)
72_Pandas.DataFrame保存并读取带pickle的系列(to_pickle、read_pickle) 要将 pandas.DataFrame、pandas.Series 对象保存为 pickle 文件,请使用 to_pickle() 方法,并使用 pd.read_pickle() 函数读取保存的 pickle 文件。 在此对…...
Redis哨兵模式和Redis Cluster模式
文章目录 🔊博主介绍🥤本文内容Redis Cluster 模式支持自动故障转移功能吗?Redis Cluster 模式支持自动故障转移功能和哨兵有什么区别?Redis Cluster 模式和哨兵模式(Sentinel)在自动故障转移方面有一些关键…...
C语言第三十二弹---自定义类型:联合和枚举
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】 目录 1、联合体 1.1、联合体类型的声明 1.2、联合体的特点 1.3、相同成员的结构体和联合体对比 1.4、联合体大小的计算 1.5、联合的⼀个练习 2、枚举类型 …...
milvus upsert流程源码分析
milvus版本:v2.3.2 整体架构: Upsert 的数据流向: 1.客户端sdk发出Upsert API请求。 import numpy as np from pymilvus import (connections,Collection, )num_entities, dim 4, 3print("start connecting to Milvus") connections.connect("default",…...
QT网络通信
九、网络 基础概念 1.1 TCP/UDP TCP/UDP UDP TCP 协议相同点:都存在于传输层,全双工通信 TCP:全双工通信、面向连接、可靠 TCP(即传输控制协议):是一种面向连接的传输层协议,它能提供高可靠性通…...
案例分析|山西某光伏发电站轨道巡检机器人解决方案
随着光伏发电技术的不断发展,光伏变电站配电室作为能量转换和输送的关键节点,承担着重要的电力分配和保护功能。然而,传统的人工巡检方式存在诸多问题,如巡检周期长、效率低、安全风险高等,已经无法满足光伏变电站配电…...
Apache POl
介绍 Apache POl是一个处理Miscrosoft Ofice各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作,一般情况下,POI都是用于操作 Excel 文件。 Apache POl 的应用场景 1.银行网银系统导出交易…...
高防服务器托管应注意什么
选择高防服务器托管主要考虑的因素:1.服务商的服务器大小。2.服务器的防御值大小。3.服务器机房的位置以及机房的资质。 具体内容如下: 1.服务器大小是按照U来定的,U是一种表示服务器外部尺寸的单位(计量单位:高度或厚…...
swagger-ui.html报错404,解决办法
swagger-ui.html报错404,解决办法!现在后端开发项目中,为了节省时间,使用swagger插件,可以方便的快捷生成接口文档。但是如果你在请求前端页面路径比如:http://127.0.0.1:7777/swagger-ui.html。找不到。那是因为你的配…...
golang 函数式编程库samber/mo使用: Future
golang 函数式编程库samber/mo使用: Future 如果您对samber/mo库不了解, 请先阅读第一篇 Option 本节讲述Future的使用,它可以帮助我们处理异步编程问题。 示例 我们先来看看下面代码的示例, 注释解释了每一步的操作。 packa…...
【Spring连载】使用Spring Data访问 MongoDB(十四)----Mongodb特有的查询方法
【Spring连载】使用Spring Data访问 MongoDB(十四)----Mongodb特有的查询方法 一、定义通用查询方法二、MongoDB特有的查询方法2.1 地理空间查询Geo-spatial Queries2.2 基于JSON的查询方法和字段限制2.3 使用SpEL表达式的基于JSON的查询2.4 全文检索查询…...
消息中间件篇之RabbitMQ-消息重复消费
一、导致重复消费的情况 1. 网络抖动。 2. 消费者挂了。 消费者消费消息后,当确认消息还没有发送到MQ时,就发生网络抖动或者消费者宕机。那当消费者恢复后,由于MQ没有收到消息,而且消费者有重试机制,消费者就会再一次消…...
常见设计模式之单例模式
单例模式 单例模式是一种常用的软件设计模式,主要目的是确保一个类在整个应用程序生命周期中只有一个实例,并提供一个全局访问点以获取该实例。 单例模式分为几种不同的实现方式,包括懒汉模式和饿汉模式。每种方式都有其特点和适用场景。例如…...
VL817-Q7 USB3.0 HUB芯片 适用于扩展坞 工控机 显示器
VL817-Q7 USB3.1 GEN1 HUB芯片 VL817-Q7 USB3.1 GEN1 HUB芯片 VIA Lab的VL817是一款现代USB 3.1 Gen 1集线器控制器,具有优化的成本结构和完全符合USB标准3.1 Gen 1规范,包括ecn和2017年1月的合规性测试更新。VL817提供双端口和双端口4端口配置&…...
【Android安全】Windows 环境下载 AOSP 源码
准备环境 安装 git 安装 Python 硬盘剩余容量最好大于 800G 打开 Git Bash,用 git 克隆源代码仓库 git clone https://android.googlesource.com/platform/manifest.git //没有梯子使用清华源 git clone https://aosp.tuna.tsinghua.edu.cn/platform/manifest.git这…...
Vue.js+SpringBoot开发快递管理系统
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 快递类型模块2.3 快递区域模块2.4 快递货架模块2.5 快递档案模块 三、界面展示3.1 登录注册3.2 快递类型3.3 快递区域3.4 快递货架3.5 快递档案3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 …...
Linux/Spectra
Enumeration nmap 第一次扫描发现系统对外开放了22,80和3306端口,端口详细信息如下 22端口运行着ssh,80端口还是http,不过不同的是打开了mysql的3306端口 TCP/80 进入首页,点击链接时,提示域名不能解析&…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...
用鸿蒙HarmonyOS5实现中国象棋小游戏的过程
下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...
保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...
恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一:HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二:Floyd 快慢指针法(…...
【java面试】微服务篇
【java面试】微服务篇 一、总体框架二、Springcloud(一)Springcloud五大组件(二)服务注册和发现1、Eureka2、Nacos (三)负载均衡1、Ribbon负载均衡流程2、Ribbon负载均衡策略3、自定义负载均衡策略4、总结 …...
