设计模式基础概念(行为模式):责任链模式(Chain Of Responsibility)

概述

责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者
该模式建议你将这些处理者连成一条链。
链上的每个处理者都有一个成员变量来保存对于下一处理者的引用。 除了处理请求外, 处理者还负责沿着链传递请求。 请求会在链上移动, 直至所有处理者都有机会对其进行处理。

  • 处理者可以决定不再沿着链传递请求, 这可高效地取消所有后续处理步骤。

结构

在这里插入图片描述

示例

该模式在核心 Java 程序库中的一些示例:

  • javax.servlet.Filter#doFilter()
  • java.util.logging.Logger#log()

伪代码实现

Base Handler(基础处理者)

abstract class BaseHandler {// 继任者protected Handler successor;public void setSuccesssor(Handler successor) {this.successor = successor;}public static Handler link(Handler first, Handler... chain) {Handler head = first; // 初始化头部为第一个中间件for (Handler nextInChain : chain) {head.setSuccesssor(nextInChain); // 将当前中间件的下一个指向链中的下一个中间件head = nextInChain; // 移动到链中的下一个中间件}return first; // 返回链的头部}/*** 子类将实现此方法以进行具体的检查。** @param params 参数* @return 返回检查结果*/public abstract boolean check(Object params);/*** 在链中的下一个对象上运行检查,或者如果我们在链的最后一个对象中则结束遍历。** @param params 参数* @return 如果没有下一个中间件,返回 true;否则返回下一个中间件的检查结果*/protected boolean checkNext(Object params) {if (next == null) {return true; // 如果没有下一个中间件,返回 true}return next.check(params); // 调用下一个中间件的检查方法}
}

Handler(处理者)

Handler(处理者)

处理者1:校验请求次数限制

public class OneHandler extends BaseHandler {private int requestPerMinute;private int requestTimes;private long currentTime;public OneHandler(int requestPerMinute) {this.requestPerMinute = requestPerMinute;this.currentTime = System.currentTimeMillis();}/*** 校验请求次数 一分钟内 是否到达requestPerMinute 达到则停止责任链*/public boolean check(Object params) {if (System.currentTimeMillis() > currentTime + 60_000) {request = 0;currentTime = System.currentTimeMillis();}request++;if (request > requestPerMinute) {System.out.println("Request limit exceeded!");Thread.currentThread().stop();}return super.checkNext(params);}
}

处理者2:

public class TwoHandler extends BaseHandler {private Server server;public TwoHandler(Server server) {this.server= server;}/*** 校验其他*/public boolean check(Object params) {server.checkOther(params);// 其他处理return super.checkNext(params);}
}

Server(其他辅助service)

定义了handler中的其他处理方法等

public class Server {private BaseHandler baseHandler;public void setMiddleware(BaseHandler baseHandler) {this.baseHandler = baseHandler;}public void checkOther(Object params) {// 其他处理逻辑}public boolean test(Object params) {if (baseHandler.check(params)) {System.out.println("Authorization have been successful!");// Do something useful here for authorized users.return true;}return false;}}

Client (客户端)

Client : 需要设置一个职责链的各环节对象串联起来。

public class ChainOfResponsibilityPattern {public static void main(String[] args) {BaseHandler handler = Middleware.link(new OneHandler(2),new TwoHandler(server));server.test(params)}
}

应用场景

程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时, 可以使用责任链模式

  • 该模式能将多个处理者连接成一条链。 接收到请求后, 它会 “询问” 每个处理者是否能够对其进行处理。 这样所有处理者都有机会来处理请求。

必须按顺序执行多个处理者时, 可以使用该模式。

  • 无论以何种顺序将处理者连接成一条链, 所有请求都会严格按照顺序通过链上的处理者。

如果所需处理者及其顺序必须在运行时进行改变, 可以使用责任链模式。

  • 如果在处理者类中有对引用成员变量的设定方法, 你将能动态地插入和移除处理者, 或者改变其顺序。

在这里插入图片描述

实现方式

  1. 声明处理者接口并描述请求处理方法的签名。

    • 确定客户端如何将请求数据传递给方法。 最灵活的方式是将请求转换为对象, 然后将其以参数的形式传递给处理函数。
  2. 在具体处理者中消除重复的样本代码, 你可以根据处理者接口创建抽象处理者基类。

    • 该类需要有一个成员变量来存储指向链上下个处理者的引用。 你可以将其设置为不可变类。 但如果你打算在运行时对链进行改变, 则需要定义一个设定方法来修改引用成员变量的值。
    • 为了使用方便, 你还可以实现处理方法的默认行为。 如果还有剩余对象, 该方法会将请求传递给下个对象。 具体处理者还能够通过调用父对象的方法来使用这一行为。
  3. 依次创建具体处理者子类并实现其处理方法。 每个处理者在接收到请求后都必须做出两个决定:

    • 是否自行处理这个请求。
    • 是否将该请求沿着链进行传递。
  4. 客户端可以自行组装链, 或者从其他对象处获得预先组装好的链。 在后一种情况下, 你必须实现工厂类以根据配置或环境设置来创建链。

    • 客户端可以触发链中的任意处理者, 而不仅仅是第一个。 请求将通过链进行传递, 直至某个处理者拒绝继续传递, 或者请求到达链尾。
    • 由于链的动态性, 客户端需要准备好处理以下情况:
      • 链中可能只有单个链接
      • 部分请求可能无法到达链尾
      • 其他请求可能直到链尾都未被处理

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

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

相关文章

小小猫棒onu替换家用光猫,薅运营商带宽羊毛,突破1000M

小小猫棒onu 一、总体步骤 1 记录原来光猫信息 主要包括SN,ploam密码,loid、loid密码、 mac、上网的vlan id等 一般gpon采用SN、ploam密码、SNploam密码三种中的一种认证方式 一般Epon采用loid(逻辑id)、mac、loid mac三种中…

【Unity 实用工具篇】 | UGUI 循环列表 SuperScrollView,快速上手使用

前言 【Unity 实用工具篇】 | UGUI 循环列表 SuperScrollView,快速上手使用一、UGUI ScrollRect拓展插件:SuperScrollView1.1 介绍1.2 效果展示1.3 使用说明及下载 二、SuperScrollView 快速上手使用2.1 LoopListView22.2 LoopGridView2.3 LoopStaggered…

【Java并发编程】信号量Semaphore详解

一、简介 Semaphore(信号量):是用来控制同时访问特定资源的线程数量,它通过协调各个线程,以保证合理的使用公共资源。 Semaphore 一般用于流量的控制,特别是公共资源有限的应用场景。例如数据库的连接&am…

Spring Boot框架下租房管理系统的设计与实现

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统,它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等,非常…

9.Linux按键驱动-工作队列

1.思路 1.1在gpio结构体中定义工作队列 1.2 在probe函数中初始化工作队列 1.3.在中断服务程序中调度工作队列 1.4工作队列处理函数&#xff1a; 2.编程 程序&#xff1a; #include <linux/module.h> #include <linux/fs.h> #include <linux/errno.h> #…

基于微信小程序实现信阳毛尖茶叶商城系统设计与实现

作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参与学生毕业答辩指导&#xff0c;…

xtu 哈希

样例输入# 2 2 1 2 4 1 3 5 7 样例输出# 2 3解题思路&#xff1a;欧拉筛素数 满足题意的素数值一定是从n/2开始的。原因&#xff1a;因为每个哈希函数值最多冲突一次&#xff0c;也就是一个哈希值最多出现2次&#xff0c;最坏的情况&#xff0c;数组中所有哈希值都出现2次&…

【判断推理】逻辑论证之一般质疑

不明确选项&#xff1a;表述不够明确&#xff0c;属于既不能加强、也不能削弱的选项 5.1 无论据有结论的一般质疑 无论据有结论&#xff1a;题干往往由“背景、分析、结论”&#xff0c;用提出反向论据的方式反驳论点。 这类题挺简单的&#xff0c;注意话题一致、主题正确&am…

手机拍证件照,换正装有领衣服及底色的方法

证件照在我们的职业生涯的关键节点是经常会用到的&#xff0c;比如毕业入职、人事档案建立、升迁履历、执业资格考试和领证等&#xff0c;这些重要的证件照往往要求使用正装照&#xff0c;有时候手头没有合适的衣服&#xff0c;或者原先的证件照背景色不符合要求&#xff0c;就…

【Fargo】18:camera获取及预览

QCameraViewfinder.ui Build started at 0:10... 1>------ Build started: Project: Fargo, Configuration: Debug Win32 ------

acaconda基础指令(实用不罗嗦,持续更新)

查看conda版本 conda --version 更新acaconda conda update Anaconda 查看有哪些虚拟环境&#xff08;三条均可&#xff09; conda env listconda info -econda info --envs 创建虚拟环境 conda create -n env_name python3.8 激活虚拟环境 conda activate env_name …

Python图像处理——基于ResNet152的人脸识别签到系统(Pytorch框架)

&#xff08;1&#xff09;数据集制作 本次使用明星做为数据集&#xff0c;首先编写爬虫函数&#xff0c;根据关键字爬取对应的明星&#xff0c;爬取结果保存至data文件夹&#xff0c;并以标签名作为文件名。具体爬取的明星如下&#xff1a; 注&#xff1a;实际应用中&#xf…

【thinkphp8】00005 thinkphp8 Db::table和Db::name的区别

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【th…

FreeRTOS 6:任务创建函数xTaskCreate分析

动态创建任务xTaskCreate xTaskCreate 1、申请堆栈内存&#xff08;返回首地址&#xff09; 2、申请任务控制块内存&#xff08;返回首地址&#xff09; 3、把前面申请的堆栈地址&#xff0c;赋值给控制块的堆栈成员 4、调用prvlnitialiseNewTask初始化任务控制块中的成员 …

linux系统安全:开源的反病毒工具ClamAV的安装配置使用和维护介绍

目录 一、概述 1、开发者 2、功能 3、特性 二、安装ClamAV 1、更新系统包列表 2、安装ClamAV 三、更新病毒库 四、配置ClamAV 1、编辑ClamAV配置文件 2、主要配置选项 &#xff08;1&#xff09;/etc/clamd.conf &#xff08;2&#xff09; /etc/freshclam.conf …

windows下安装python库wordCloud报错

换电脑安装wordcloud半天安装失败&#xff0c;记录一下遇到的坑&#xff0c;也给大家节省点时间。 方法1&#xff1a; 错误呢就是下面这个&#xff0c;说没c编译器&#xff0c;要不就去他给的地址上安装一下&#xff0c;我安装了一下好像没什么选&#xff0c;也没太敢勾选吗&a…

2025 - AI人工智能药物设计 - 中药网络药理学和毒理学的研究

中药网络药理学和毒理学的研究 TCMSP&#xff1a;https://old.tcmsp-e.com/tcmsp.php 然后去pubchem选择&#xff1a;输入Molecule Name 然后进行匹配&#xff1a;得到了smiles 再次通过smiles&#xff1a;COC1C(CC(C2C1OC(CC2O)C3CCCCC3)O)O 然后再次输入&#xff1a;http…

C语言基础(五)【控制语句与循环(上)学习篇】

文章目录 前言一、if - else 语句二、switch-case 语句三、while 循环四、for 循环五、do - while 循环六、break 语句七、continue 语句八、go to 语句总结 前言 C语言是结构化的程序设计语言&#xff0c;这里的结构指的是顺序结构、选择结构、循环结构&#xff0c;因此提供了…

中国人寿财险青岛市分公司:科技赋能,车险服务再升级

中国人寿财险青岛市分公司积极响应国家号召&#xff0c;大力推进车险综合改革&#xff0c;以科技赋能车险服务&#xff0c;实现服务再升级。公司利用AI技术&#xff0c;实现车险报案的自动化处理&#xff0c;大幅缩短了理赔周期。同时&#xff0c;公司还通过大数据分析&#xf…

【力扣】[Java版] 刷题笔记-101. 对称二叉树

题目&#xff1a;101. 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 解题思路 可以理解为遍历对比&#xff0c;最简单的方法就是递归。 解题过程 递归&#xff1a;左右子树分开遍历&#xff0c;左子树遵循根、左、右的顺序&#xff0c;右子树循…