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

设计模式十四:责任链模式(Chain of Responsibility Pattern)

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求。
在责任链模式中,多个处理者对象被连接成一个链。当接收到一个请求时,每个处理者会判断自己是否有能力来处理该请求,如果可以处理则直接处理,如果不能处理,则将请求传递给链中的下一个处理者。这样,请求就会依次经过整个链,直到找到一个合适的处理者处理请求或者请求到达链的末端仍然没有处理者能够处理。

责任链模式适用于以下场景:

  1. 请求需要被多个对象处理:当一个请求需要经过多个对象的处理时,可以使用责任链模式。每个对象都能够判断自己是否能够处理该请求,从而实现责任的分担和协作。
  2. 需要动态指定处理对象:通过将处理者对象组织成一个链,可以在运行时动态地指定处理请求的对象集合。这样可以灵活地增加或删除处理者,并且不影响客户端代码。
  3. 可以按照顺序执行处理步骤:如果有一系列相关的处理步骤需要按照特定的顺序执行,可以使用责任链模式。每个处理者只负责完成自己的处理步骤,从而简化了客户端代码,并且提高了代码的可维护性。
  4. 需要避免请求发送者和接收者之间的耦合:责任链模式通过将请求发送者和接收者解耦,使得发送者不需要知道是哪个具体处理者来处理请求。这样可以降低系统的耦合度并提高代码的灵活性。
  5. 有时候需要在处理请求之前进行预处理或后处理操作:责任链模式可以方便地在处理请求之前或之后进行其他操作,例如日志记录、数据统计等。
    责任链模式适用于在处理对象之间存在松散耦合、需要动态指定处理对象并且能够按照特定顺序执行处理步骤的情况下使用。当然,具体是否使用责任链模式还要根据具体问题的需求和限制来决定。

责任链模式的主要角色

在责任链模式中,每个具体处理者都有可能处理请求,也有可能将请求转发给链中的下一个处理者。这样,在调用方和具体处理者之间形成了一条职责链,请求会按照职责链上的顺序依次传递,直到有一个处理者能够处理请求,或者职责链的末端没有处理者能够处理请求时结束。通过动态地组织处理者对象,责任链模式可以灵活地处理请求,并且能够简化代码结构。

  1. 抽象处理者(Handler):定义一个接口,声明了处理请求的方法,并且可以拥有一个指向下一处理者的引用。该角色可以是抽象类或接口。
  2. 具体处理者(Concrete Handler):实现抽象处理者接口,对请求进行具体的处理。如果自己无法处理请求,可以将请求转发给下一个处理者。
  3. 客户端(Client):创建处理者对象,并且将请求发送到处理者链中的第一个处理者对象。客户端通常不关心具体的处理者对象,只需要知道链中的第一个处理者。

责任链模式的java代码实例

实现处理一个系统bug,由初级程序员到高级程序员到架构师顺级处理
抽象处理者

public interface Handler {/*** 下一个处理者** @param handler*/void setNext(Handler handler);/*** 处理bug** @param bugLevel* @return*/String dealBug(int bugLevel);}

具体处理者

/*** 初级程序员*/
public class JuniorProgrammer implements Handler {private Handler nextHandler;@Overridepublic void setNext(Handler handler) {this.nextHandler = handler;}@Overridepublic String dealBug(int bugLevel) {String res = "";if (bugLevel < 3) {System.out.println("JuniorProgrammer deal this bug!");} else if (nextHandler != null) {System.out.println("JuniorProgrammer hand over to SeniorProgrammer this bug!");res = nextHandler.dealBug(bugLevel);} else {System.out.println("JuniorProgrammer throw this bug!");res = "bug is throw into the street";}return res;}
}/*** 高级程序员*/
public class SeniorProgrammer implements Handler {private Handler nextHandler;@Overridepublic void setNext(Handler handler) {this.nextHandler = handler;}@Overridepublic String dealBug(int bugLevel) {String res = "";if (bugLevel < 6) {System.out.println("SeniorProgrammer deal this bug!");} else if (nextHandler != null) {System.out.println("SeniorProgrammer hand over to Architect this bug!");res = nextHandler.dealBug(bugLevel);} else {System.out.println("SeniorProgrammer throw this bug!");res = "bug is throw into the street";}return res;}}/*** 架构师*/
public class Architect implements Handler {private Handler nextHandler;@Overridepublic void setNext(Handler handler) {this.nextHandler = handler;}@Overridepublic String dealBug(int bugLevel) {String res = "";if (bugLevel < 8) {System.out.println("Architect deal this bug!");} else if (nextHandler != null) {System.out.println("Architect hand over to BOSS this bug!");res = nextHandler.dealBug(bugLevel);} else {System.out.println("Architect is run!");res = "bug is throw into the street";}return res;}
}

客户端

public static void main(String[] args) {Handler juniorProgrammer = new JuniorProgrammer();Handler seniorProgrammer = new SeniorProgrammer();Handler architect = new Architect();juniorProgrammer.setNext(seniorProgrammer);seniorProgrammer.setNext(architect);System.out.println(juniorProgrammer.dealBug(2));//结果:// JuniorProgrammer deal this bug!System.out.println(juniorProgrammer.dealBug(5));//结果:// JuniorProgrammer hand over to SeniorProgrammer this bug!// SeniorProgrammer deal this bug!System.out.println(juniorProgrammer.dealBug(9));//结果:// JuniorProgrammer hand over to SeniorProgrammer this bug!// SeniorProgrammer hand over to Architect this bug!// Architect is run!// bug is throw into the street}

责任链模式的优缺点

责任链模式有以下优点:

  1. 解耦职责:责任链模式可以将请求的发送者与接收者解耦,发送者不需要知道具体的接收者是谁,而是通过链式传递请求,每个处理者只负责处理自己所能处理的请求。
  2. 灵活性和扩展性:可以动态地添加、修改或删除处理者,灵活配置责任链,满足不同的业务需求。新的请求处理者可以很方便地添加到责任链的末尾,同时也可以很容易地拆分或重组责任链。
  3. 可靠性:由于请求在责任链中依次传递,每个处理者只负责处理自己所能处理的请求,因此可以保证每个请求都会被处理。

责任链模式的缺点包括:

  1. 请求可能无法被处理:如果没有正确地配置责任链,或者所有处理者都无法处理某个请求,那么该请求可能无法被处理。
  2. 运行时性能开销:由于请求的传递是通过链式调用实现的,每个处理者都需要进行判断是否能够处理请求,并将请求转发给下一个处理者,可能会导致一定的运行时性能开销。
  3. 可能导致系统复杂性增加:过多或过少的处理者以及复杂的处理逻辑可能会导致责任链变得非常复杂,增加系统的复杂性。需要仔细设计和管理责任链,以确保其简洁、高效。

相关文章:

设计模式十四:责任链模式(Chain of Responsibility Pattern)

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为设计模式&#xff0c;它允许你将请求沿着处理者链进行传递&#xff0c;直到有一个处理者能够处理该请求。 在责任链模式中&#xff0c;多个处理者对象被连接成一个链。当接收到一个请求时&#xf…...

将商城项目放到docker-centos7中

1、docker pull centos:7 2、docker run -d -it --privileged 仓库名称/shopcentos:1.1 /usr/sbin/init 注意&#xff1a; /usr/sbin/init 必须加&#xff0c;否则没法使用systemctl启动mysql 3、安装mysql教程 安装msyql教程&#xff1a;https://blog.csdn.net/davice_li…...

C# Winform 自动获取 软件版本号

C# Winform如何自动获取版本号 方案一 缺点是不适配&#xff0c;clickones发布的版本 public static string GetVersion() {try {return System.Deployment.Application.ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString();}catch{return System.Ref…...

基于C++实现了最小反馈弧集问题的三种近似算法(GreedyFAS、SortFAS、PageRankFAS)

该项目是一个基于链式前向星存图、boost&#xff08;boost::hash、asio线程池&#xff09;以及emhash7/8的非官方实现&#xff0c;实现了最小反馈弧集问题的三种近似算法。该问题是在有向图中找到最小的反馈弧集&#xff0c;其中反馈弧集是指一组弧&#xff0c;使得从这些反馈弧…...

奶牛用餐 优先队列 java

&#x1f468;‍&#x1f3eb; 奶牛用餐 约翰的农场有 n n n 头奶牛&#xff0c;编号 1 s i m n 1 \\sim n 1simn。 每天奶牛们都要去食堂用餐。 食堂一共有 k k k 个座位&#xff0c;也就是说同一时间最多可以容纳 k k k 头奶牛同时用餐。 已知&#xff0c;第 i i i …...

包管理机制pip3

pip3 安装pip3 安装pip3 apt install python3-pip yum install python3-pip从仓库出发的命令 查询仓库信息 // 获取默认pip3源 pip3 config get global.index-url查询所有软件包 查询已经安装的所有软件包 pip3 list从软件包出发的命令 从软件包名出发查询其他信息 查询…...

liunx在线安装tomcat

1、在线安装 https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.91/bin/apache-tomcat-8.5.91.tar.gz 执行&#xff1a;wget --no-check-certificate https://dlcdn.apache.org/tomcat/tomcat-8/v8.5.91/bin/apache-tomcat-8.5.91.tar.gz ps:或者直接把tar.gz扔服务器 2、 编…...

导入示例工程出现error: failed to start ability. Error while Launching activity错误的解决办法

导入华为健康生活应用&#xff08;ArkTS&#xff09;&#xff0c;使用DevEco Studio打开&#xff0c;运行报错&#xff1a; error: failed to start ability. Error while Launching activity解决办法&#xff1a;修改module.json5里面exported的值&#xff0c;由false改为tr…...

【深入了解PyTorch】PyTorch分布式训练:多GPU、数据并行与模型并行

【深入了解PyTorch】PyTorch分布式训练:多GPU、数据并行与模型并行 PyTorch分布式训练:多GPU、数据并行与模型并行1. 分布式训练简介2. 多GPU训练3. 数据并行4. 模型并行5. 总结PyTorch分布式训练:多GPU、数据并行与模型并行 在深度学习领域,模型的复杂性和数据集的巨大规…...

linux 下 网卡命名改名

Linux 操作系统的网卡设备的传统命名方式是 eth0、eth1、eth2等&#xff0c;而 CentOS7 提供了不同的命名规则&#xff0c;默认是网卡命名会根据网卡的硬件信息&#xff0c;插槽位置等有关&#xff1b;来分配。这样做的优点是命名全自动的、可预知的&#xff0c;缺点是比 eth0、…...

6.2.0在线编辑:GrapeCity Documents for Word (GcWord) Crack

GrapeCity Word 文档 (GcWord) 支持 Office Math 函数以及转换为 MathML GcWord 现在支持在 Word 文档中创建和编辑 Office Math 内容。GcWord 中的 OMath 支持包括完整的 API&#xff0c;可处理科学、数学和通用 Word 文档中广泛使用的数学符号、公式和方程。以下是通过 OMa…...

为什么需要智能指针?

为什么需要智能指针&#xff1f; 解决忘记释放内存导致内存泄漏的问题。解决异常安全问题。 #include<iostream> using namespace std;int div() {int a, b;cin >> a >> b;if (b 0)throw invalid_argument("除0错误");return a / b; } void Func(…...

《华为认证》L2TP VPN配置

配置接口ip地址&#xff0c;并且将防火墙的接口加入对应的安全区域 。 LNS的G1/0/0 IP为202.1.1.1 1、配置LNS的缺省路由&#xff1a; ip route-static 0.0.0.0 0.0.0.0 202.1.1.2 2、通过WEB 界面配置防火墙的 L2TP VPN 浏览器输入&#xff1a; https://202.1.1.1:8443/def…...

【JVM】JVM垃圾收集器

文章目录 什么是JVM垃圾收集器四种垃圾收集器&#xff08;按类型分&#xff09;1.串行垃圾收集器(效率低&#xff09;2.并行垃圾收集器(JDK8默认使用此垃圾回收器&#xff09;3.CMS&#xff08;并发&#xff09;垃圾收集器(只针对老年代垃圾回收的&#xff09; 什么是JVM垃圾收…...

StarGANv2: Diverse Image Synthesis for Multiple Domains论文解读及实现(一)

StarGAN v2: Diverse Image Synthesis for Multiple Domainsp github:https://github.com/clovaai/stargan-v2 1 模型架构 模型主要架构由四部分组成 ①Generator、②Mapping network、③Style encoder、④Discriminator Generator&#xff1a;G网络 生成模型G将输入图片x转换…...

Go Gin 中使用 JWT

一、JWT JWT全称JSON Web Token是一种跨域认证解决方案&#xff0c;属于一个开放的标准&#xff0c;它规定了一种Token实现方式&#xff0c;目前多用于前后端分离项目和OAuth2.0业务场景下。 二、为什么要用在你的Gin中使用JWT 传统的Cookie-Sesson模式占用服务器内存, 拓展性…...

AWS中Lambda集成SNS

1.创建Lambda 在Lambda中&#xff0c;创建名为AWSSNSDemo的函数 use strict console.log(loading function); var aws require(aws-sdk); var docClient new aws.DynamoDB.DocumentClient(); aws.config.regionap-southeast-1;exports.handler function(event,context,cal…...

Mac下⬇️Git如何下载/上传远程仓库

使用终端检查电脑是否安装Git git --version 通过此文章安装Git ➡️ ​​​​​​​传送门&#x1f310; 方式1⃣️使用终端操作 1.下载——克隆远程仓库到本地 git clone [远程地址] 例&#xff1a;git clone https://gitee.com/lcannal/movie.git​ 2.编…...

linux 命令--常用关机命令

1.使用shutdown命令 shutdown命令是Linux系统下最常用的关机命令之一。它可以让系统在指定时间内进行关机或者重启操作。例如&#xff0c;下面的命令可以让系统在5分钟后进行关机操作&#xff1a; sudo shutdown -h5其中&#xff0c;“-h”表示关机&#xff0c;“5”表示5分钟…...

ttf-dejavu fontconfig字体

ttf-dejavu fontconfig是验证码&#xff0c;pdf&#xff0c;excel时需要用到的字体 编辑dockerfile&#xff0c;先切换国内镜像源&#xff0c;默认alpinelinux是国外源&#xff0c;下载包会很慢 vim Dockerfile FROM alpine:latest RUN sed -i s/dl-cdn.alpinelinux.org/mirr…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

Unity UGUI Button事件流程

场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...