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

【设计模式-4.3】行为型——责任链模式

说明:本文介绍设计模式中行为型设计模式中的,责任链模式;

审批流程

责任链模式属于行为型设计模式,关注于对象的行为。责任链模式非常典型的案例,就是审批流程的实现。如一个报销单的审批流程,根据报销单金额大小,需要不同的职位领导审批,金额越大,审批人的职务越高,如下:

在这里插入图片描述

代码如下:

(Staff,财务专员,审批金额不超过5000)

/*** 财务专员*/
public class Staff {private String name;public Staff(String name) {this.name = name;}/*** 审批* @param amount 金额* @return 是否通过*/public boolean approve(double amount) {if (amount <= 5000) {System.out.println(name + "审批通过");return true;} else {System.out.println("驳回申请。【" + name + "】");return false;}}public String getName() {return name;}
}

(Manager,财务经理,审批金额不超过1w)

/*** 财务经理*/
public class Manager {private String name;public Manager(String name) {this.name = name;}/*** 审批* @param amount 金额* @return 是否通过*/public boolean approve(double amount) {if (amount <= 10000) {System.out.println(name + "审批通过");return true;} else {System.out.println("驳回申请。【" + name + "】");return false;}}public String getName() {return name;}
}

(CFO,财务总监,审批金额不超过10w,否则直接找Boss)

/*** 财务总监*/
public class CFO {private String name;public CFO(String name) {this.name = name;}/*** 审批* @param amount 金额* @return 是否通过*/public boolean approve(double amount) {if (amount <= 100000) {System.out.println(name + "审批通过");return true;} else {System.out.println("驳回申请。【" + name + "】");return false;}}public String getName() {return name;}
}

(Client,客户端,审批金额5000)

/*** 客户端*/
public class Client {public static void main(String[] args) {int amount = 8000;Staff staff = new Staff("财务专员");Manager manager = new Manager("财务经理");CFO cfo = new CFO("财务总监");if (!staff.approve(amount)) {if (!manager.approve(amount)) {if (!cfo.approve(amount)) {System.out.println("找Boss");}}}}
}

(在财务经理这里审批通过)

在这里插入图片描述

通过上面的代码实现,可以看到客户端有多层的if判断,代码臃肿,不够灵活。

我们可以考虑将审批报销流程的各层人员抽象出来,成一个审批人,然后再在该类中再注入一个审批人为上级审批人。另外,创建一个抽象的审批方法,让其他审核人职务继承这个审批人类,实现其审批方法。方法内判断当前审批金额,该审核人职务不能审核其金额时,交给上级审批人审核。

如下:

(Approver,审批人抽象类,有审批人、下一个审批人,抽象审批方法)

/*** 审批人*/
public abstract class Approver {/*** 审批人姓名*/protected String name;/*** 下一个审批人*/protected Approver nextApprover;public Approver(String name) {this.name = name;}/*** 设置下一个审批人* @param nextApprover* @return*/public Approver setNextApprover(Approver nextApprover) {this.nextApprover = nextApprover;return this.nextApprover;}/*** 审批* @param amount*/public abstract void approve(int amount);
}

(Staff,财务专员,审批金额不大于5000,否则交给下一位审批人审批)

/*** 财务专员*/
public class Staff extends Approver{public Staff(String name) {super(name);}@Overridepublic void approve(int amount) {if (amount <= 5000) {System.out.println("审批通过。【" + name + "】");} else {System.out.println("金额太大,无法审批,交由上级处理。【" + name + "】");this.nextApprover.approve(amount);}}
}

(Manager,财务经理,审批金额不大于1w,否则交给下一位审批人审批)

/*** 财务经理*/
public class Manager extends Approver{public Manager(String name) {super(name);}@Overridepublic void approve(int amount) {if (amount <= 10000) {System.out.println("审批通过。【" + name + "】");} else {System.out.println("金额太大,无法审批,交由上级处理。【" + name + "】");this.nextApprover.approve(amount);}}
}

(CFO,财务总监,审批金额不大于10w,否则找老板处理)

/*** 财务总监*/
public class CFO extends Approver{public CFO(String name) {super(name);}@Overridepublic void approve(int amount) {if (amount <= 100000) {System.out.println("审批通过。【" + name + "】");} else {System.out.println("金额太大,无法审批,请找老板处理。【" + name + "】");}}
}

(Client,客户端)

/*** 客户端*/
public class Client {public static void main(String[] args) {// 审批金额int amount = 200000;// 审批人Staff staff = new Staff("财务专员");Manager manager = new Manager("财务经理");CFO cfo = new CFO("财务总监");// 设置下一个审批人manager.setNextApprover(cfo);staff.setNextApprover(manager);// 审批staff.approve(amount);}
}

执行结果,因为审批金额为20w,需要找老板处理;

在这里插入图片描述

或者使用链式编程,直接用一行代码搞定;

/*** 客户端*/
public class Client {public static void main(String[] args) {// 审批金额int amount = 200000;new Staff("财务专员").setNextApprover(new Manager("财务经理")).setNextApprover(new CFO("财务总监")).approve(amount);}
}

区别就在于使用链式编程,只会执行对应审批人内的if代码块;

在这里插入图片描述

以上是责任链模式的内容,责任链模式是很容易理解的设计模式,和我们日常生活非常紧密。但代码却不容易理解,在审批人对象里面再注入一个审批人对象,不容易想明白。

总结

本文参考《设计模式的艺术》、《秒懂设计模式》两书

相关文章:

【设计模式-4.3】行为型——责任链模式

说明&#xff1a;本文介绍设计模式中行为型设计模式中的&#xff0c;责任链模式&#xff1b; 审批流程 责任链模式属于行为型设计模式&#xff0c;关注于对象的行为。责任链模式非常典型的案例&#xff0c;就是审批流程的实现。如一个报销单的审批流程&#xff0c;根据报销单…...

单片机语言--C51语言的数据类型以及存储类型以及一些基本运算

C51语言 本文主要涉及C51语言的一些基本知识&#xff0c;比如C51语言的数据类型以及存储类型以及一些基本运算。 文章目录 C51语言一、 C51与标准C的比较二、 C51语言中的数据类型与存储类型2.1、C51的扩展数据类型2.2、数据存储类型 三、 C51的基本运算3.1 算术运算符3.2 逻辑…...

《每天一个Linux命令》 -- (5)通过sshkey密钥登录服务器

欢迎阅读《每天一个Linux命令》系列&#xff01;在本篇文章中&#xff0c;将介绍通过密钥生成&#xff0c;使用公钥连接管理服务器。 概念 SSH 密钥是用于安全地访问远程服务器的一种方法。SSH 密钥由一对密钥组成&#xff1a;公钥和私钥。公钥存储在远程服务器上&#xff0c;…...

kubernetes的服务发现(二)

如前面的文章我们说了&#xff0c;kubernetes的服务发现是服务端发现模式。它有一个服务注册中心&#xff0c;使用DNS作为服务的注册表。每个集群都会运行一个DNS服务&#xff0c;默认是CoreDNS服务。每个服务都会在这个DNS中注册。注册的大致过程&#xff1a; 1、向kube-apise…...

【矩阵论】Chapter 4—特征值和特征向量知识点总结复习

文章目录 1 特征值和特征向量2 对角化3 Schur定理和正规矩阵4 Python求解 1 特征值和特征向量 定义 设 σ \sigma σ为数域 F F F上线性空间 V V V上的一个线性变换&#xff0c;一个非零向量 v ∈ V v\in V v∈V&#xff0c;如果存在一个 λ ∈ F \lambda \in F λ∈F使得 σ (…...

Linux 进程地址空间

知识回顾 在 C 语言的学习过程中&#xff0c;我们知道内存是可以被划分为栈区&#xff0c;堆区&#xff0c;全局数据区&#xff0c;字符常量区&#xff0c;代码区的。他的空间排布可能是下面的样子&#xff1a; 其中&#xff0c;全局数据区&#xff0c;可以划分为已初始化全局…...

websocket vue操作

let websocket: WebSocket; /** websocket测试 */ function connectWebsocket() {if (typeof WebSocket "undefined") {console.log("您的浏览器不支持WebSocket");return;}// let ip window.location.hostname ":8080";let ip "10.192…...

腾讯云CentOS8 jenkins war安装jenkins步骤文档

腾讯云CentOS8 jenkins war安装jenkins步骤文档 一、安装jdk 1.1 上传jdk-11.0.20_linux-x64_bin.tar.gz 1.2 解压jdk安装包文件 tar -zxvf jdk*.tar.gz 1.3 在/usr/local 目录下创建java目录 cd /usr/local mkdir java 1.4 切到java目录&#xff0c;把jdk解压文件改名为jd…...

Linux: glibc: net/if.h vs linux/if.h

最近看到一段代码改动,用net/if.h替换了linux/if.h。仔细看了看这两个的区别: https://stackoverflow.com/questions/20082433/what-is-the-difference-between-linux-if-h-and-net-if-h 从网上搜了一下看到如下的一个编译错误,如果同时使用这两个if.h文件,需要将net/if.h…...

使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题

文章目录 一、 篇头二、 操作步骤2.1 编译AOSP AS工程文件2.2 将AOSP导入Android Studio2.3 切到Project试图2.4 等待index结束2.5 下载缺失的JDK 1.82.6 导入完成 三、 导入AS的好处3.1 本文案例演示源码编译错误AS对比同文件其余地方的调用AS错误提示依赖AS做错误修正 一、 篇…...

python random详解

文章目录 random简单示例1. 生成随机浮点数&#xff1a;2. 生成指定范围内的随机整数&#xff1a;3. 从序列中随机选择元素&#xff1a;4. 打乱序列顺序&#xff1a; 常用的方法及其解释和例子&#xff1a;1. random()&#xff1a;该方法返回一个0到1之间的随机浮点数。例如&am…...

java-两个列表进行比较,判断那些是需要新增的、删除的、和更新的

文章目录 前言两个列表进行比较&#xff0c;判断那些是需要新增的、删除的、和更新的 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实…...

【WPF.NET开发】WPF中的对话框

目录 1、消息框 2、通用对话框 3、自定义对话框 实现对话框 4、打开对话框的 UI 元素 4.1 菜单项 4.2 按钮 5、返回结果 5.1 模式对话框 5.2 处理响应 5.3 非模式对话框 Windows Presentation Foundation (WPF) 为你提供了自行设计对话框的方法。 对话框是窗口&…...

NLP项目实战01之电影评论分类

介绍&#xff1a; 欢迎来到本篇文章&#xff01;在这里&#xff0c;我们将探讨一个常见而重要的自然语言处理任务——文本分类。具体而言&#xff0c;我们将关注情感分析任务&#xff0c;即通过分析电影评论的情感来判断评论是正面的、负面的。 展示&#xff1a; 训练展示如下…...

一款可无限扩展的软件定时器开源框架项目代码

摘自链接 时间片轮询架构如何稳定高效实现&#xff0c;取代传统的标志位判断方式&#xff0c;更优雅更方便地管理程序的时间触发操作。 可以在STM32单片机上运行。...

GRE与顺丰圆通快递盒子

1. DNS污染 随想&#xff1a; 在输入一串网址后&#xff0c;会发生如下变化如果你在系统中配置了 Hosts 文件&#xff0c;那么电脑会先查询 Hosts 文件如果 Hosts 里面没有这个别名&#xff0c;就通过域名服务器查询域名服务器回应了&#xff0c;那么你的电脑就可以根据域名服…...

12.Mysql 多表数据横向合并和纵向合并

Mysql 函数参考和扩展&#xff1a;Mysql 常用函数和基础查询、 Mysql 官网 Mysql 语法执行顺序如下&#xff0c;一定要清楚&#xff01;&#xff01;&#xff01;运算符相关&#xff0c;可前往 Mysql 基础语法和执行顺序扩展。 (8) select (9) distinct (11)<columns_name…...

线性回归与逻辑回归:深入解析机器学习的基石模型

目录 一、线性回归 二、逻辑回归 逻辑回归算法和 KNN 算法的区别 分类算法评价维度...

电脑待机怎么设置?让你的电脑更加节能

在日常使用电脑的过程中&#xff0c;合理设置待机模式是一项省电且环保的好习惯。然而&#xff0c;许多用户对于如何设置电脑待机感到困扰。那么电脑待机怎么设置呢&#xff1f;本文将深入探讨三种常用的电脑待机设置方法&#xff0c;通过详细的步骤&#xff0c;帮助用户更好地…...

数据库对象介绍与实践:视图、函数、存储过程、触发器和物化视图

文章目录 一、视图&#xff08;View&#xff09;1、概念2、基本操作1&#xff09;创建视图2&#xff09;修改视图3&#xff09;删除视图4&#xff09;使用视图 3、使用场景4、实践 二、函数&#xff08;Function&#xff09;1、概念2、基本操作1&#xff09;创建函数2&#xff…...

arm平台编译so文件回顾

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、几个点二、回顾过程 1.上来就执行Makefile2.编译第三方开源库.a文件 2.1 build.sh脚本2.2 Makefile3.最终编译三、其它知识点总结 前言 提示&#xff1a;这…...

【数据结构】顺序表的定义和运算

目录 1.初始化 2.插入 3.删除 4.查找 5.修改 6.长度 7.遍历 8.完整代码 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da;。 &…...

idea使用maven的package打包时提示“找不到符号”或“找不到包”

介绍&#xff1a;由于我们的项目是多模块开发项目&#xff0c;在打包时有些模块内容更新导致其他模块在引用该模块时不能正确引入。 情况一&#xff1a;找不到符号 情况一&#xff1a;找不到包 错误代码部分展示&#xff1a; Failure to find com.xxx.xxxx:xxx:pom:0.5 in …...

MetricBeat监控MySQL

目录 一、安装部署 二、开启mysql监控模块 三、编辑mysql配置文件 四、启动Metricbeat 五、查看监控图表 一、安装部署 metriceat的安装部署参考章节&#xff1a; Metricbeat安装使用&#xff0c;这里不再赘述。 二、开启mysql监控模块 进入metricbeat安装目录 ./metricb…...

Child Mind Institute - Detect Sleep States(2023年第一次Kaggle拿到了银牌总结)

感谢 感谢艾兄&#xff08;大佬带队&#xff09;、rich师弟&#xff08;师弟通过这次比赛机械转码成功、耐心学习&#xff09;、张同学&#xff08;也很有耐心的在学习&#xff09;&#xff0c;感谢开源方案&#xff08;开源就是银牌&#xff09;&#xff0c;在此基础上一个月…...

Esxi7Esxi8设置VMFSL虚拟闪存的大小

Esxi7Esxi8设置VMFSL虚拟闪存的大小 ESXi7,8 默认安装会分配一个 VMFSL(VMFS-L)(Local VMFS)很大空间(120G), 感觉很浪费, 实际给 8G 就可以了, 最少 6G , 经实验,给2G没法安装 . Esxi7是虚拟闪存的 修改的方法是: 在安装时修改 设置 autoPartitionOSDataSize8192 在cdromBoo…...

vue2+electron桌面端一体机应用

vue2+electron项目 前言:公司有一个项目需要用Vue转成exe,首先我使用vue-cli脚手架搭建vue2项目,然后安装electron 安装electron 这一步骤可以省略,安装electron-builder时会自动安装electron npm i electron 安装electron-builder vue add electron-builder 项目中多出…...

目标检测——OverFeat算法解读

论文&#xff1a;OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks 作者&#xff1a;Pierre Sermanet, David Eigen, Xiang Zhang, Michael Mathieu, Rob Fergus, Yann LeCun 链接&#xff1a;https://arxiv.org/abs/1312.6229 文章…...

vue获取主机id和IP地址

获取主机id和IP地址 在vue.config.js const os require(“os”); function getNetworkIp() { let needHost “”; // 打开的host try { // 获得网络接口列表 let network os.networkInterfaces(); for (let dev in network) { let iface network[dev]; for (let i 0; i …...

在pytorch中自定义dataset读取数据

这篇是我对哔哩哔哩up主 霹雳吧啦Wz 的视频的文字版学习笔记 感谢他对知识的分享 有关我们数据读取预训练 以及如何将它打包成一个一个batch输入我们的网络的 首先我们来看一下之前我们在讲resnet网络时所使用的源码 我们去使用了官方实现的image folder去读取我们的图像数据 然…...