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 进入首页,点击链接时,提示域名不能解析&…...
ComfyUI-AnimateDiff-Evolved深度解析:掌握动画生成的进阶实战指南
ComfyUI-AnimateDiff-Evolved深度解析:掌握动画生成的进阶实战指南 【免费下载链接】ComfyUI-AnimateDiff-Evolved Improved AnimateDiff for ComfyUI and Advanced Sampling Support 项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-AnimateDiff-Evolved …...
层次分析法(AHP)翻车实录:我踩过的3个大坑和避坑指南
层次分析法实战避坑指南:从理论到落地的关键挑战 去年数学建模竞赛中,我们团队在决策分析环节选择了层次分析法(AHP),结果却因为几个隐蔽的陷阱导致最终结果与实际情况严重偏离。这次经历让我深刻认识到——掌握AHP的基…...
魔幻C++ 用最大公因数 求最小公倍数
//最大公因数 int gcd(int a,int b){if(b0)return a;else return gcd(b,a%b); } //最小公倍数 int lcm(int a,int b){return a/gcd(a,b)*b; }cout<<lcm(28,8);...
Chapter 14: Link Initialization Training
Chapter 14: Link Initialization & Training 书籍: PCI Express Technology 3.0 (MindShare Press, 2012) 页码: Book Pages 487-520 | PDF Pages 547-580 学习日期: 2026-04-13本章概要 本章描述 PCIe 链路初始化和训练过程,包括 TS1/TS2 有序集、极性检测、L…...
中型钢材全自动液压打捆机设计(论文+CAD图纸+答辩+翻译……)
中型钢材全自动液压打捆机是针对钢材加工环节中捆扎效率与质量提升需求设计的核心设备。传统人工捆扎或半自动设备存在捆扎力度不均、速度慢、劳动强度大等问题,尤其在处理大量中型钢材时,人工操作易因疲劳导致捆扎松动,影响运输安全。该设备…...
从投稿到接收:一份给Applied Soft Computing作者的完整Latex排版与提交保姆级教程
从投稿到接收:一份给Applied Soft Computing作者的完整LaTeX排版与提交保姆级教程 当你完成了一篇高质量的研究论文,准备向Applied Soft Computing投稿时,如何确保你的稿件在技术格式上完全符合期刊要求?这篇文章将带你走过从下载…...
Vue3 + AntV X6 实战:手把手教你从零搭建一个可拖拽、自定义连线的流程图编辑器
Vue3 AntV X6 实战:构建企业级可定制流程图编辑器 在数字化转型浪潮中,可视化流程编辑工具已成为众多业务系统的核心组件。无论是复杂的工作流引擎、数据血缘分析平台,还是智能决策系统,都需要一个能够直观呈现和编辑节点关系的界…...
不止于连接:用ADB命令深度管理你的华为荣耀V9(文件传输、进程查看实战)
不止于连接:用ADB命令深度管理你的华为荣耀V9(文件传输、进程查看实战) 当你已经成功用ADB连接上荣耀V9,就像拿到了一把通往Android系统深处的钥匙。但大多数人只用来开个门就停下了——其实门后藏着整套工具间。上周帮同事调试应…...
告别VLC!手把手教你编译支持H265的FFmpeg,用ffplay播放RTMP流(附避坑指南)
从零构建支持H265的RTMP播放器:FFmpeg深度定制指南 在流媒体技术快速迭代的今天,H265编码以其卓越的压缩效率成为4K/8K超高清内容的首选方案。然而,当我们需要通过RTMP协议传输H265视频时,却面临着传统播放器兼容性不足的困境。本…...
排班管理系统功能全拆解:如何用排班管理系统解决制造业多班次调度难题
在制造业数字化转型的浪潮中,排班管理系统正逐渐成为工厂标准化管理的标配。面对复杂的“多班次调度”需求,传统的Excel手工排班已难以支撑高效的生产节奏。一套成熟的排班管理系统,不仅能解决人力浪费、排班冲突等核心难题,还能通…...
