20、设计模式之责任链模式(Chain)

一、什么是责任链模式
责任链模式属于行为型模式,在这个模式中,通常使用一条链来处理请求,该请求沿着链的顺序传递,直到有对象处理该请求为止,从而达到解耦请求发送者和请求处理者的目的。

二、组成
抽象处理器(Handler):定义处理请求的接口,提供一个抽象方法用于处理请求,并定义一个指向后继处理器的引用。

具体处理器(ConcreteHandler):实现抽象处理器接口,用于处理请求。如果当前处理器不能处理请求,则将请求传递给后继处理器。

三、优缺点
优点:

降低耦合度:请求发送者和接收者都没有对方的明确信息,而是通过抽象处理器来链接。实现了请求的发送者和处理者之间的解耦。
灵活性:可以动态地增加或删除处理器,方便扩展和维护。
易于实现: 在责任链模式中,每个具体的处理器只需要实现自己的功能即可,不需要知道整个请求链的存在,这样更加容易实现其功能。
缺点:

不能保证请求一定会被处理:在责任链模式中,由于请求的处理是由多个对象负责的,所以不能保证请求一定会被处理,存在漏洞导致请求无响应的风险。
性能问题:在应用责任链模式时需要控制链中的处理器数量,过多的处理器会导致处理时间增加,从而影响系统性能。
调试困难:责任链模式中的处理器是动态组合的,处理逻辑较为复杂,因此需要进行详细的测试和调试。
四、应用场景
4.1 应用实例
请假申请流程:公司内部的请假申请一般需要经过多级审批,每个审批者的职责不同,可以通过责任链模式实现申请者与处理者之间的解耦,让申请者的请求依次经过各个处理者的处理,直到最终得到审批结果。

商品退换货:在线商场中,如果用户需要对商品进行退换货,涉及到订单创建、退货申请、快递配送等诸多步骤,这些步骤可以通过责任链模式实现,让每个处理者负责自己的任务,将责任链串接起来,以便完成整个退换货流程。

请求处理中心:当一个请求需要经过多个处理节点进行处理时,可以采用责任链模式来组织这些处理节点,使得请求在节点之间循环传递,直到得到最终结果。例如,大型网站的访问请求处理中心,就可以采用责任链模式来处理请求。

系统安全中心:当系统发生安全威胁时,可以采用责任链模式来组织安全相关的处理节点,对异常数据进行检测和拦截,保障系统安全稳定运行。

4.2 程序场景
请求的处理顺序不确定:如果一个系统中存在多个处理请求的对象,且请求的处理可能需要先后顺序,则可以采用责任链模式,让不同的处理对象构成责任链,依次对请求进行处理。
有多个对象可以处理请求:如果一个请求可能需要由多个对象来进行处理,而这些处理对象之间相互独立,不需要知道其他处理对象的存在,则可以采用责任链模式来实现请求的处理。
需要动态安排处理流程:如果处理流程需要动态安排,可以通过动态组合责任链节点来实现。即根据实际需求,动态安排责任链的执行顺序和强度。
需要在不影响代码整体结构的情况下,进行功能扩展:使用责任链模式可以方便地扩展系统的功能,对业务逻辑和系统结构的初始设计基本无影响,只需要添加新的处理节点、修改处理节点间的联系即可。
五、代码实现
下面以学校请假审批流程为例。我们假设有三个教师,分别是班主任、年级组长和校长。如果一位教师请假,需要经过这三个人的审批,但请假天数的不同就需要不同的审批者。

5.0 UML类图

在这里插入图片描述
5.1 Approver(审批者)

/**
 * 
 * 审批者,包括班主任、年级组长和校长
 */
public abstract class Approver {
    String name;
    Approver next;
 
    public Approver(String name){
        this.name=name;
    }
 
    //设置下一个审批者
    public void setNext(Approver next){
        this.next=next;
    }
 
    //审批请求
    public abstract void approve(LeaveRequest request);
}

5.2 Master(校长)

/**
 *
 * 校长 请假天数大于七天,年级组长和班主任都没权力审批,交给校长
 */
public class Master extends Approver{
 
    public Master(String name){
        super(name);
    }
 
    @Override
    public void approve(LeaveRequest request) {
        if (request.getDays() > 7) {
            System.out.println("校长" + name + "审批了" + request.getName() + "的请假申请,天数为" + request.getDays());
        } else {
            if (next != null) {
                next.approve(request);
            }
        }
    }
}

5.3 GradeLeader(年级组长)

/**
 * 
 * 年级组长,请假天数2-7天,班主任处理不了,交给年级主任
 */
public class GradeLeader extends Approver {
 
    public GradeLeader(String name){
        super(name);
    }
 
    @Override
    public void approve(LeaveRequest request) {
        if (request.getDays() <= 7) {
            System.out.println("年级组长" + name + "审批" + request.getName() + "的请假申请,天数为" + request.getDays());
        } else {
            if (next != null) {
                System.out.println("年级组长审批不了,交由下一级");
                next.approve(request);
            }
        }
    }
}

5.4 ClassAdviser(班主任)

/**
 * 
 * 班主任,请假天数2天内,班主任就可以审批
 */
public class ClassAdviser extends Approver{
 
    public ClassAdviser(String name){
        super(name);
    }
 
    @Override
    public void approve(LeaveRequest request) {
        if (request.getDays() <= 2) {
            System.out.println("班主任" + name + "审批" + request.getName() + "的请假申请,天数为" + request.getDays());
        } else {
            if (next != null) {
                System.out.println("班主任审批不了,交由下一级");
                next.approve(request);
            }
        }
    }
}

5.5 LeaveRequest(请假信息)

import lombok.AllArgsConstructor;
import lombok.Data;
/**
 * 
 * 请假信息
 */
@AllArgsConstructor
@Data
public class LeaveRequest {
    //请假人姓名
    private String name;
    //请假天数
    private Integer days;
}

5.6 TestChain

/**
 * 
 * 责任链模式
 */
@SpringBootTest
public class TestChain {
    @Test
    void testChain(){
        Approver classAdviser = new ClassAdviser("张三");
        Approver gradeLeader = new GradeLeader("李四");
        Approver schoolMaster = new Master("王五");
 
        //组织责任链
        classAdviser.setNext(gradeLeader);
        gradeLeader.setNext(schoolMaster);
 
        //发起请求
        LeaveRequest request = new LeaveRequest("小明", 10);
        classAdviser.approve(request);
    }
}

在这里插入图片描述
5.7 总结
在这个例子中,每个审批者对应一个Approver对象,班主任、年级组长和校长分别继承自Approver类。每个Approver对象都有一个next属性,代表下一个审批者,这样就形成了一个责任链。在处理请求的时候,如果当前审批者可以处理请求,就处理请求;否则将请求传递给下一个审批者处理。
可以看到,在这个例子中,如果请假天数小于等于2天,班主任就处理请求;如果请假天数小于等于7天,年级组长就处理请求;如果请假天数大于7天,校长就处理请求。如果当前审批者无法处理请求,就将请求传递给下一个审批者处理,直到所有审批者都处理完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/453051.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML超链接标签

文章目录 1. 作用2. 常用属性3. 模拟小米回到顶部 1. 作用 主要作用&#xff1a;实现页面的跳转。 2. 常用属性 href&#xff1a;指定要跳转到的 urltarget &#xff1a;跳转时在如何打开链接文档 _blank&#xff1a;在新窗口打开_self&#xff1a;在本窗口打开&#xff08;…

案例分析篇13:系统分析与设计考点(2024年软考高级系统架构设计师冲刺知识点总结系列文章)

专栏系列文章推荐: 2024高级系统架构设计师备考资料(高频考点&真题&经验)https://blog.csdn.net/seeker1994/category_12593400.html 【历年案例分析真题考点汇总】与【专栏文章案例分析高频考点目录】(2024年软考高级系统架构设计师冲刺知识点总结-案例分析篇-…

Net Core 使用Mongodb操作文件(上传,下载)

Net Core 使用Mongodb操作文件&#xff08;上传&#xff0c;下载&#xff09; 1.Mongodb GridFS 文件操作帮助类。 GridFS 介绍 https://baike.baidu.com/item/GridFS/6342715?fraladdin DLL源码&#xff1a;https://gitee.com/chenjianhua1985/mongodb-client-encapsulati…

学习笔记-华为IPD转型2020:1,IPD的重要意义

华为产品开发转型&#xff1a;IPD计划 大多数公司发现&#xff0c;当公司大幅增长时&#xff0c;在较小规模上有效的管理实践不再有效。产品开发过程也是如此。随着华为的发展&#xff0c;该公司遇到了产品故障率更高、开发周期更长和研发成本增加等问题。然后&#xff0c;它转…

vulntarget-k - 内网渗透

标签 xxl-job rce Spring-Cloud-CVE-2022-22947 nacos auth bypass iox 靶机难度比较简单&#xff0c;都是用用 exp 就好了 拓扑图 网卡设置 首先需要使用虚拟网络编辑器&#xff0c;增加 VMnet1、VMnet2、VMnet3 对三张网卡设置子网 IP VMnet1 192.168.100.0 VMnet2 1…

BOOTMGR is missing 问题

同事一台win2k8的虚机在重启后无法引导开机&#xff0c;提示如下信息&#xff1a; 开始就觉得是引导分区设置错了。遂从网上下了一个winpe的镜像&#xff0c;装载到虚机“光驱”中&#xff0c;从光盘引导启动。打开“磁盘管理”后发现&#xff0c;果然&#xff0c;未安装系统…

【趣味学算法】03_兑换钱币

注&#xff1a; 本系列仅为个人学习笔记&#xff0c;学习内容为《算法小讲堂》&#xff08;视频传送门&#xff09;&#xff0c;通俗易懂适合编程入门小白&#xff0c;需要具备python语言基础&#xff0c;本人小白&#xff0c;如内容有误感谢您的批评指正 要将 50 元的软妹币兑…

LeetCode——贪心算法(Java)

贪心算法 简介[简单] 455. 分发饼干[中等] 376. 摆动序列[中等] 53. 最大子数组和[中等] 122. 买卖股票的最佳时机 II[中等] 55. 跳跃游戏 简介 记录一下自己刷题的历程以及代码。写题过程中参考了 代码随想录的刷题路线。会附上一些个人的思路&#xff0c;如果有错误&#xf…

SAP 读写生产订单长文本简介

通常在物料主数据,生产订单,采购订单中都会维护长文本的信息在业务数据中。但是我们在获取长文本的时候需要调用函数才能获取到对应业务数据的长文本的信息。 我们以获取生产订单中的长文本为例 首先需要获取到这个长文本的文本对象,文本名,文本标识 我们可以通过后台表S…

【知识库系统】使用SpringSecurity进行身份认证

一、理论知识部分 SpringSecurity 的官网文档地址&#xff1a;SpringSecurity 这里以24年3月份的 6.2.2 版本为例&#xff0c;记录一下学习过程。 1. SpringSecurity 是基于 Servlet Filters 的&#xff0c;而 Servlet Filters 中的流程如下&#xff1a;首先由客户端 Client…

[LeetCode][LCR 194]二叉树的最近公共祖先

题目 LCR 194. 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 例如&#xff0c;给定如下二叉树: root [3,5,1,6,2,0,8,null,null,7,4] 示例 1: 输入: root [3,5,1,6,2,0,8,null,null,7,4], p 5, q 1 输出: 3 解释: 节点 5 和节点 1 的最…

数据库系统概念(第二周 第一堂)

前言 本文的所有知识点、图片均来自《数据库系统概念》&#xff08;黑宝书&#xff09;、山东大学李晖老师PPT。不可用于商业用途转发。 回顾 上周最后一个知识点说到数据库三级模式结构&#xff0c;在这个结构里面我们设立了模式/内模式映像、内模式/外模式映像&#xff0c;主…

Python之闭包

一、概念 在函数嵌套的前提下&#xff0c;内层函数引用外层函数的变量(包括参数)&#xff0c;外层函数又把内层函数当做返回值进行返回。 这个内层函数所引用的外层变量称为 “闭包” def test(): # 外层函数a 33 # 外部变量def test2(): # 内层函数print(a)return test2newFu…

网络计算机

TCP/IP四层模型 应用层&#xff1a;位于传输层之上&#xff0c;主要提供两个设备上的应用程序之间信息交换的服务&#xff0c;它定义了信息交换的格式&#xff0c;消息会交给下一层传输层来传递。我们把应用层交互的数据单元称为报文。应用层工作在操作系统的用户态&#xff0…

Android自定义view从入门到高级

简介 什么是自定义view&#xff1f;我认为只要不是编译器直接提供可以使用的view&#xff0c;都可以认为是自定义view。自定义view主要分为两大类&#xff0c;第一类自定义view可以通过系统提供的各种view组合&#xff0c;样式变化实现的view。第二类是通过继承view或者ViewGro…

捍卫数据保护:预防和缓解.mallox勒索病毒的威胁

导言&#xff1a; 在当今数字化时代&#xff0c;我们与世界各地的人们通过网络连接在一起&#xff0c;享受着前所未有的便利。然而&#xff0c;随着科技的进步&#xff0c;网络犯罪也在不断演变&#xff0c;.mallox勒索病毒便是其中之一&#xff0c;给无数用户带来了困扰。本文…

【SpringCloud微服务实战07】Sentinel 服务保护

Sentinel 是阿里巴巴开源的一款微服务流量控制组件。主要作用: 流量控制:避免因瞬间高并发流量而导致服务故障流。超时处理、线程隔离、降级熔断:避免因服务故障引起的雪崩问题。一、Sentinel 安装 1、安装Sentinel控制台,下载jar包并启动:Releases alibaba/Sentinel G…

【HiVT】HiVT轨迹预测代码环境配置及训练

0.简介 github项目链接 论文链接 Argoverse 1.1验证集的预期性能是&#xff1a; Models minADE minFDE MR HiVT-64 0.69 1.03 0.10 HiVT-128 0.66 0.97 0.09 1. 拉取代码仓库 git clone https://github.com/ZikangZhou/HiVT.git cd HiVT2. 创建conda环境 conda create -n H…

Java 启动参数 -- 和 -D写法的区别

当我们配置启动1个java 项目通常需要带一些参数 例如 -Denv uat , --spring.profiles.activedev 这些 那么用-D 和 – 的写法区别是什么&#xff1f; 双横线写法 其中这种写法基本上是spring 和 spring 框架独有 最常用的无非是就是上面提到的 --spring.profiles.activede…

LiveGBS流媒体平台GB/T28181功能-海康摄像头国标语音对讲大华摄像头国标语音对讲GB28181语音对讲需要的设备及服务准备

LiveGBS海康摄像头国标语音对讲大华摄像头国标语音对讲GB28181语音对讲需要的设备及服务准备 1、背景2、准备2.1、服务端必备条件&#xff08;注意&#xff09;2.2、准备语音对讲设备2.2.1、 大华摄像机2.2.1.1、 配置接入示例2.2.1.2、 配置音频通道编号 2.2.2、 海康摄像机2.…