Java设计模式-职责链模式Chain of Responsibility

news2024/12/21 23:42:39

在这里插入图片描述

介绍

  1. 职责链模式(Chain of Responsibility Pattern), 又叫 责任链模式,为请求创建了一个接收者对象的链(简单示意图)。这种模式对请求的发送者和接收者进行解耦。
  2. 职责链模式通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
  3. 这种类型的设计模式属于行为型模式。

原理类图

在这里插入图片描述

  • 对原理类图的说明-即(职责链模式的角色及职责)
  1. Handler : 抽象的处理者, 定义了一个处理请求的接口, 同时含义另外 Handler。
  2. ConcreteHandlerA , B 是具体的处理者, 处理它自己负责的请求, 可以访问它的后继者(即下一个处理者), 如果可以处理当前请求,则处理,否则就将该请求交个 后继者去处理,从而形成一个职责链。
  3. Request , 含义很多属性,表示一个请求。

实战案例

  • 解决 OA 系统采购审批
  1. 应用实例要求
    编写程序完成学校 OA 系统的采购审批项目:需求
    采购员采购教学器材
    如果金额 小于等于 5000, 由教学主任审批
    如果金额 小于等于 10000, 由院长审批
    如果金额 小于等于 30000, 由副校长审批
    如果金额 超过 30000 以上,有校长审批

  2. 思路分析和图解(类图)
    在这里插入图片描述

代码实现

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 CollegeApprover extends Approver {
	public CollegeApprover(String name) {
		super(name);
	}

	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		if (purchaseRequest.getPrice() < 5000 && purchaseRequest.getPrice() <= 10000) {
			System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
		} else {
			approver.processRequest(purchaseRequest);
		}
	}
}
public class DepartmentApprover extends Approver {
	public DepartmentApprover(String name) {
		super(name);
	}

	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		if (purchaseRequest.getPrice() <= 5000) {
			System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
		} else {
			approver.processRequest(purchaseRequest);
		}
	}
}
//请求类
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 class SchoolMasterApprover extends Approver {
	public SchoolMasterApprover(String name) {
		super(name);
	}

	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		if (purchaseRequest.getPrice() > 30000) {
			System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
		} else {
			approver.processRequest(purchaseRequest);
		}
	}
}
public class ViceSchoolMasterApprover extends Approver {
	public ViceSchoolMasterApprover(String name) {
		super(name);
	}

	@Override
	public void processRequest(PurchaseRequest purchaseRequest) {
		if (purchaseRequest.getPrice() < 10000 && purchaseRequest.getPrice() <= 30000) {
			System.out.println(" 请求编号 id= " + purchaseRequest.getId() + " 被 " + this.name + " 处理");
		} else {
			approver.processRequest(purchaseRequest);
		}

	}
}
public class Client {
	public static void main(String[] args) {
		//创建一个请求
		PurchaseRequest purchaseRequest = new PurchaseRequest(1, 31000, 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);
		viceSchoolMasterApprover.processRequest(purchaseRequest);
	}
}

源码分析

  1. SpringMVC-HandlerExecutionChain 类就使用到职责链模式
  2. SpringMVC 请求流程简图
  3. 代码分析+Debug 源码+说明:
    在这里插入图片描述
  1. springmvc 请求的流程图中,执行了 拦截器相关方法 interceptor.preHandler 等等
  2. 在处理 SpringMvc 请求时,使用到职责链模式还使用到适配器模式
  3. HandlerExecutionChain 主要负责的是请求拦截器的执行和请求处理,但是他本身不处理请求,只是将请求分配
    给链上注册处理器执行,这是职责链实现方式,减少职责链本身与处理逻辑之间的耦合,规范了处理流程
  4. HandlerExecutionChain 维护了 HandlerInterceptor 的集合, 可以向其中注册相应的拦截器.

注意事项

  1. 将请求和处理分开,实现解耦,提高系统的灵活性。
  2. 简化了对象,使对象不需要知道链的结构。
  3. 性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在 Handler 中设置一个最大节点数量,在 setNext()方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地破坏系统性能。
  4. 调试不方便。采用了类似递归的方式,调试时逻辑可能比较复杂。
  5. 最佳应用场景:有多个对象可以处理同一个请求时,比如:多级请求、请假/加薪等审批流程、Java Web 中 Tomcat对 Encoding 的处理、拦截器。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言#include的用法详解

#include叫做文件包含命令&#xff0c;用来引入对应的头文件&#xff08;.h文件&#xff09;。#include 也是C语言预处理命令的一种。#include 的处理过程很简单&#xff0c;就是将头文件的内容插入到该命令所在的位置&#xff0c;从而把头文件和当前源文件连接成一个源文件&am…

Oracle数据库故障处理-存储单块读hang分析处理

1 故障描述 2023年1月27日下午接到业务反馈数据库存在大量的锁表阻塞信息&#xff0c;并且业务的页面以及数据库的一些查询均处于阻塞状态&#xff0c;简单的查询sql也需要查询很长时间且未返回结果,数据库hang状态。 2 故障原因分析 2.1 数据库层面分析 接到业务反馈后&am…

如果放在几年前,无法想到互联网会蜕变成今天这样一副模样

如果放在几年前&#xff0c;你是万万无法想到互联网会蜕变成今天这样一副模样。尽管如此&#xff0c;这样一种蜕变却在真实地发生着。不知道你有没有发现就连前两年火爆的短视频人们都懒得刷了。所有的这一切都在告诉我们&#xff0c;互联网正在发生一场深刻而又彻底的嬗变。如…

SQL Server数据库版本总结

一、为什么要写这篇文章 之所以专门写一篇文章来整理归纳SQL Server各个版本的功能区别&#xff0c;是因为遇到过两次真实的客户案例&#xff0c;因为数据库版本选取不当&#xff0c;导致生产系统宕机的情况。 案例一 某客户安装了 32位 版本的SQL Server 2008 R2 数据库&…

人工智能轨道交通行业周刊-第31期(2023.1.16-1.29)

本期关键词&#xff1a;磁悬浮原理、小米石、通信铁塔维护、桥隧工巡检、地方铁路十大新闻 1 整理涉及公众号名单 1.1 行业类 RT轨道交通中关村轨道交通产业服务平台人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路…

element 日期组件实现只能选择小时或者只能选择小时、分钟

前言 在使用 element 框架时&#xff0c;总是会有一些满足不了现有项目需求的问题&#xff0c;这个时候就需要我们对 element 的组件进行改造&#xff0c;最近有一个需求就是要求日期组件只能选择年月日时&#xff0c;不要分钟和秒&#xff0c;找了一圈&#xff0c;发现 elemen…

【Markdown】CSDN 的 Markdown 编辑器锚点使用-进阶篇

1. 原始 Markdown 代码 1.1 “目录”元素 [TOC](8.6 InnoDB ClusterSet 的状态和拓扑)1.2 “1号标题-1”元素 # InnoDB ClusterSet 状态1.3 “1号标题-2”元素 <h1> <a id"innodb-clusterset-topology">InnoDB ClusterSet 拓扑</a> </h1>…

压缩包文件如何设置和删除密码

压缩软件除了可以压缩和解压文件&#xff0c;还可以作为加密软件&#xff0c;给压缩的文件设置密码来保护文件。 今天就来看下两个常用的压缩软件是如何设置和删除密码的。 先说说WinRAR这个最常用的压缩软件&#xff0c;它可以根据不同的需求设置单次密码和永久自动加密。 …

2023年度国家自然科学基金项目开放申报及注意事项

根据国家自然科学基金委员会发布的通告&#xff0c;2023年国家自然科学基金项目申报系统已于1月15日开放。知识人网整理了主要内容&#xff0c;提醒申报者注意。一、日程节点&#xff1a;1.集中接收工作于2023年3月1日开始&#xff0c;3月20日16时截止。2.申请人于2023年1月15日…

笔记本电脑拆机并更换固态硬盘的方法

本文介绍为笔记本电脑拆机、更换固态硬盘的具体方法。 在文章Win10电脑出现No Bootable Device且无法开机或开机后蓝屏无限重启的多个解决方法&#xff08;https://blog.csdn.net/zhebushibiaoshifu/article/details/122923896&#xff09;中我们提到&#xff0c;一些由电脑硬盘…

高频算法:删除有序数组中的重复项

今天要讲的算法题是LeetCode上的第26题&#xff0c;先贴题目&#xff1a; 首先题目中给出了几个比较关键的条件&#xff0c;首先就是升序排列的数组&#xff0c;这样的话至少我们不需要进行排序的操作&#xff0c;直接从前向后进行比较&#xff0c;我们就能知道数组中的哪些元…

基于SpringBoot、Mybatis-Generator实现数据库表自动生成全套后台代码

背景我们在日常开发过程&#xff0c;大多数都是使用主流MVC架构&#xff0c;如下图所示。从图中可以看出&#xff0c;我们主要的业务代码基本都是从Controller->Service->Dao/Mapper&#xff0c;由Dao/Mapper则通过Mybatis连接数据库连接池的方式与数据库进行指令数据交互…

实现简单的栈与队列

前言&#xff1a;前面已经详细地介绍了基本的顺序表和链表&#xff0c;这次要介绍的是数据结构中的栈与队列。从本质上来说&#xff0c;二者是特殊的线性表&#xff0c;是依赖于顺序表或链表来实现的&#xff0c;所以只要能够很好地掌握顺序表和链表&#xff0c;再了解清楚栈与…

STM32F103学习笔记(11)——压力传感器GZP6859D使用

一、简介 数据手册&#xff1a;https://item.szlcsc.com/3590436.html GZP6859D 型压力传感器采用 SOP6 封装形式&#xff0c;内部集成了高精度 ADC 芯片&#xff0c;对传感器芯片输出的偏移、灵敏度、温漂和非线性进行数字补偿&#xff0c;以供电电压为参考&#xff0c;产生一…

基于Java实现对Excel表格数据的读写(附B站详细讲解视频)

文章目录 Maven依赖设置导入相应jar包 读取.xlsx表格文件数据 写入数据到.xlsx表格文件 读写后缀名为.xls类型的表格文件&#xff08;旧版表格文件&#xff09; 详细视频教程 Maven依赖设置导入相应jar包 <project xmlns"http://maven.apache.org/POM/4.0.0" …

论文理解【Offline RL】——【One-step】Offline RL Without Off-Policy Evaluation

标题&#xff1a;Offline RL Without Off-Policy Evaluation文章链接&#xff1a;Offline RL Without Off-Policy Evaluation代码&#xff1a;davidbrandfonbrener/onestep-rl发表&#xff1a;NIPS 2021领域&#xff1a;离线强化学习&#xff08;offline/batch RL&#xff09;—…

【深度学习】知识蒸馏原理以及实践从0到1

文章目录前言1、知识蒸馏1.1 是什么&#xff1f;1.2 训练流程1.3 问题与挑战2、落地使用2.1 后续问题&#xff1a;总结前言 有没有什么方法可以在不扩展硬件的情况下利用这些强大但庞大的模型来训练最先进的模型&#xff1f;目前&#xff0c;有三种方法可以压缩神经网络&#…

一文搞懂JDK8 HashMap源码

目录前言常量和变量构造器put方法resize扩容get方法前言 HashMap的源码非常经典&#xff0c;里面用到了哈希表、链表、红黑树等数据结构&#xff0c;而且又是用纯Java实现的&#xff0c;所以成为了Java程序员必读的源码之一。 事先了解下哈希表&#xff08;散列表&#xff09…

portraiture2023手动磨皮的p图插件

可以手动磨皮的p图软件&#xff0c;大部分美颜软件只能一键磨皮或简单调整磨皮强度&#xff0c;本文会介绍一款可自动、可手动磨皮的p图软件。人像p图软件哪个好用&#xff1f;本文还会盘点一下好用的人像p图软件。 portraiture2023功能特点 2x性能和精细的输出质量将您的皮肤…

AES加密算法

AES算法原理 对称加密算法&#xff08;用于取代DES算法&#xff0c;发展历史DES-3DES-AES&#xff09; 明文长度固定为128位&#xff08;DES&#xff1a;64位&#xff09;&#xff0c;密钥长度可128位、192位、256位&#xff08;DES&#xff1a;64位&#xff09; 加密原理 …