设计模式基础概念(行为模式):责任链模式(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.rhkb.cn/news/461395.html

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

相关文章

centos7 安装python3.9.4,解决import ssl异常

本篇文章介绍如何在centos7中安装python3.9.4(下文简称python3),解决python3安装后import ssl模块失败问题,为什么我要在centos7中安装python呢,因为我需要在服务器中跑python数据处理脚本。 安装python3同时解决import ssl模块失败问题总共包…

【分布式技术】分布式序列算法Snowflake深入解读

文章目录 概述Snowflake算法的构成:Snowflake算法的特点:Snowflake算法存在的问题: 🔍 雪片算法在分布式系统中是如何保证ID的唯一性和有序性的?唯一性(Uniqueness)有序性(Orderline…

纯CSS实现UI设计中常见的丝带效果(5)

原文传送门:纯CSS实现UI设计中常见的丝带效果 网页中的丝带效果在设计中扮演着多重角色,其作用可以归纳为以下几个方面: 视觉吸引与装饰 增强视觉吸引力:丝带效果以其独特的形态和色彩,能够迅速吸引用户的注意力&…

TP41Y阀套式排污阀

在现代工业领域中,阀门作为一种关键的控制元件,广泛应用于各种流体系统中。其中,TP41Y阀套式排污阀以其独特的设计和优异的性能,在石油、天然气、化工等行业中占据了重要的地位。本文将对TP41Y阀套式排污阀进行详细的专业解析&…

Python | Leetcode Python题解之第522题最长特殊序列II

题目&#xff1a; 题解&#xff1a; class Solution:def findLUSlength(self, strs: List[str]) -> int:def is_subseq(s: str, t: str) -> bool:pt_s pt_t 0while pt_s < len(s) and pt_t < len(t):if s[pt_s] t[pt_t]:pt_s 1pt_t 1return pt_s len(s)ans …

Flink SQL中Changelog事件乱序处理原理

本文围绕Flink SQL实时数据处理中的Changelog事件乱序问题&#xff0c;分析了Flink SQL中Changelog事件乱序问题的原因&#xff0c;并提供了解决方案以及处理Changelog事件乱序的建议。以帮助您更好地理解Changelog的概念和应用&#xff0c;更加高效地使用Flink SQL进行实时数据…

HTML CSS

目录 1. 什么是HTML 2. 什么是CSS ? 3. 基础标签 & 样式 3.1 新浪新闻-标题实现 3.1.1 标题排版 3.1.1.1 分析 3.1.1.2 标签 3.1.1.3 实现 3.1.2 标题样式 3.1.2.1 CSS引入方式 3.1.2.2 颜色表示 3.1.2.3 标题字体颜色 3.1.2.4 CSS选择器 3.1.2.5 发布时间字…

Open3D(C++) 基于法线微分的点云分割

目录 一、算法原理二、代码实现三、结果展示1、原始点云2、分割结果本文由CSDN点云侠原创,原文链接,首发于:2024年11月1日。 一、算法原理 使用C++版本Open3D复现的PCL里边基于法线微分的分割算法。PCL 基于法线微分(DoN)的点云分割【2024最新版】。网上有大量相关算法介…

Xcode 15.4 运行flutter项目,看不到报错信息详情?

Xcode升级后&#xff0c;遇到了奇怪的事情&#xff1a; 运行flutter项目&#xff0c;左侧栏显示有报错信息&#xff0c;但是点击并没有跳转出具体的error详情。【之前都会自己跳转出来的&#xff0c;升级后真的是无厘头】 方案&#xff1a; 点击左侧导航栏最右边的图标——>…

Java基础(8)异常

目录 1.前言 2.正文 2.1异常的引入 2.2异常的类型 2.2.1编译时异常 2.2.2运行时异常 2.3区分Exception与Error 2.4异常的声明&#xff0c;抛出与捕获 2.4.1throw 2.4.2throws 2.4.2try-catch与finally 2.6自定义异常 3.小结 1.前言 哈喽大家好啊&#xff0c;Java…

解决rabbitmq-plugins enable rabbitmq_delayed_message_exchange :plugins_not_found

问题&#xff1a;我是在docker-compose环境部署的 services:rabbitmq:image: rabbitmq:4.0-managementrestart: alwayscontainer_name: rabbitmqports:- 5672:5672- 15672:15672environment:RABBITMQ_DEFAULT_USER: rabbitRABBITMQ_DEFAULT_PASS: 123456volumes:- ./rabbitmq/…

JavaScript语法基础——变量,数据类型,运算符和程序控制语句(小白友好篇,手把手教你学会!)

一、JavaScript概述 JavaScript是一种高级编程语言&#xff0c;常用于网页开发和服务器端应用程序。它是一种动态类型语言&#xff0c;可以在浏览器中直接解释执行&#xff0c;而不需要编译。 脚本&#xff08;Script&#xff09;是一种与计算机程序相关的指令集或代码块&…

Android 中View.post的用法

View.post 是 Android 中 View 类的一个方法&#xff0c;它允许我们在视图 (View) 完成其布局 (Layout) 阶段后&#xff0c;将一个任务放到主线程的消息队列中&#xff0c;以便稍后执行。这种方式通常用于确保在 View 的尺寸、位置等布局属性已经计算完成后执行某些操作。 基本…

健康之路押注医药零售:毛利率下滑亏损扩大,医疗咨询人次大幅减少

《港湾商业观察》黄懿 2024年9月13日&#xff0c;健康之路股份有限公司&#xff08;下称“健康之路”&#xff09;再次递表港交所&#xff0c;建银国际为独家保荐人。健康之路国内运营主体为健康之路&#xff08;中国&#xff09;信息技术有限公司和福建健康之路信息技术有限公…

在pycharm中使用sqllite

在pycharm中使用sqllite sqllite 简介 SQLite 是一个开源的、轻量级的、关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它设计用于嵌入到应用程序中&#xff0c;并且可以在无需外部服务器进程的情况下运行。SQLite 提供了完整的 SQL 语言支持&#xff0c;允…

游戏启动失败:8种修复xinput1_3.dll错误的几种方法教程,轻松解决xinput1_3.dll错误

当你准备好在一天的工作后放松一下&#xff0c;启动你最爱的游戏&#xff0c;却突然收到一个“xinput1_3.dll 丢失”的错误消息&#xff0c;这无疑是令人沮丧的。幸运的是&#xff0c;xinput1_3.dll丢失问题通常可以通过几个简单的步骤来解决。本文将详细介绍这些步骤&#xff…

多线程和线程同步基础篇学习笔记(Linux)

大丙老师教学视频&#xff1a;10-线程死锁_哔哩哔哩_bilibili 目录 大丙老师教学视频&#xff1a;10-线程死锁_哔哩哔哩_bilibili 线程概念 为什么要有线程 线程和进程的区别 在处理多任务的时候为什么线程数量不是越多越好? Linux提供的线程API 主要接口 线程创建 pth…

DDRPHY数字IC后端设计实现系列专题

在对 LPDDR3 物理层接口模块进行后端设计之前&#xff0c;需要对该模块的功能结 构以及后端物理设计流程的相关理论进行深入的分析和研究。本章第一节详细分 析了本次 LPDDR3 物理层接口模块的结构&#xff0c;为该模块的布图布局的合理规划奠 定了理论基础&#xff0c;并且分析…

【笔记】数据结构与算法

参考链接&#xff1a;数据结构(全) 参考链接&#xff1a;数据结构与算法学习笔记 一些PPT的整理&#xff0c;思路很不错&#xff0c;主要是理解角度吧&#xff0c;自己干啃书的时候结合一下会比较不错 0.总论 1.数据 注&#xff1a;图是一种数据结构&#xff01;&#xff01;…

无人机救援系统基本组成

无人机救援系统基本组成 1. 源由2. 组成2.1 无人机载具2.1.1 多旋翼2.1.2 垂起固定翼2.1.3 智能避障2.1.4 物资投递 2.2 智能吊舱2.2.1 云台2.2.2 高清摄像2.2.3 红外热成像2.2.4 激光测距2.2.5 目标跟踪 2.3 通讯链路2.3.1 超长距离通信2.3.2 长距离通信2.3.3 中等距离通信 2.…