20 设计模式之职责链模式(问题处理案例)
一、什么是职责链模式
职责链模式是一种行为型设计模式,它允许将请求沿着处理者的链进行传递,直到有一个处理者能够处理它为止。换句话说,它将请求的发送者和接收者解耦,使得多个对象都有机会处理这个请求,从而避免了将请求直接发送给具体的处理者。
在职责链模式中,多个处理者对象形成一个链,客户端将请求传递给链中的第一个处理者,由第一个处理者决定是自己处理请求,还是将请求传递给下一个处理者,直到请求被处理或者链末尾没有处理者为止。
二、职责链模式的结构
- Handler(处理者):定义处理请求的接口,并且可以访问下一个处理者。
- ConcreteHandler(具体处理者):实现了处理请求的具体逻辑,如果能够处理该请求,则处理它,如果不能处理,则将请求传递给链中的下一个处理者。
- Client(客户端):发起请求并传递给链中的第一个处理者。
三、职责链模式的优点
- 降低耦合性:请求发送者和请求接收者解耦,发送者无需知道具体处理者。
- 灵活性:可以灵活地组织处理者链,可以动态地改变链的结构。
- 简化代码:职责链模式可以避免多重条件语句,使代码更简洁。
四、职责链模式的缺点
- 链过长:如果链太长,可能会导致性能问题。
- 处理不当:如果没有合适的处理者,可能会造成请求得不到处理。
五、案例讲解:客服支持系统
假设我们有一个客服支持系统,客户提交的问题根据其优先级需要经过不同层级的客服人员处理。优先级较低的问题由初级客服处理,优先级较高的问题由技术支持人员处理,如果问题依然没有解决,那么会交给经理来处理。
我们可以使用职责链模式来处理这个场景。以下是完整的代码实现。
六、代码实现
1.问题设计(SupportTicket)
public class SupportTicket {private String description; // 问题描述private int priority; // 问题优先级,数值越大表示优先级越高public SupportTicket(String description, int priority) {this.description = description;this.priority = priority;}public String getDescription() {return description;}public int getPriority() {return priority;}
}
SupportTicket 类表示客户提交的问题,包含问题的描述和优先级。
2.抽象支持处理者(SupportHandler)
public abstract class SupportHandler {private SupportHandler nextHandler; // 下一个处理者// 设置下一个处理者public void setNextHandler(SupportHandler nextHandler){this.nextHandler = nextHandler;}// 获取下一个处理者public SupportHandler getNextHandler(){return nextHandler;}// 处理请求的方法public abstract void handleTicket(SupportTicket ticket);
}
SupportHandler 是职责链模式中的抽象处理者,它定义了处理请求的方法 handleTicket,并且维护了一个指向下一个处理者的引用(nextHandler)。
3.初级支持处理者(JuniorSupport)
public class JuniorSupport extends SupportHandler{@Overridepublic void handleTicket(SupportTicket ticket) {if(ticket.getPriority() <= 2){System.out.println("初级客服处理问题:"+ticket.getDescription());} else if (getNextHandler() != null) {getNextHandler().handleTicket(ticket); // 传递给下一个处理者} else {System.out.println("问题过大,需要汇报给总部处理!!!");}}
}
JuniorSupport 是一个具体处理者类,当问题的优先级小于等于 2 时,它会处理该问题。如果问题优先级较高,它会将请求传递给下一个处理者。
4.技术支持处理者(TechSupport)
public class TechSupport extends SupportHandler{@Overridepublic void handleTicket(SupportTicket ticket) {if(ticket.getPriority() <= 4){System.out.println("技术员处理问题:"+ticket.getDescription());} else if (getNextHandler() != null) {getNextHandler().handleTicket(ticket); // 传递给下一个处理者} else {System.out.println("问题过大,需要汇报给总部处理!!!");}}
}
TechSupport 处理优先级小于等于 4 的问题,其他问题会传递给下一个处理者。
5.经理支持处理者(ManagerSupport)
public class ManagerSupport extends SupportHandler{@Overridepublic void handleTicket(SupportTicket ticket) {if(ticket.getPriority() <= 10){System.out.println("经理处理问题:"+ticket.getDescription());} else if (getNextHandler() != null) {getNextHandler().handleTicket(ticket);} else {System.out.println("问题过大,需要汇报给总部处理!!!");}}
}
ManagerSupport 处理优先级小于等于 10 的问题,其他问题会传递给下一个处理者,直到链的末尾。
6.测试类(TestChain)
public class TestChain {public static void main(String[] args) {// 问题声明SupportTicket ticket1 = new SupportTicket("线路混乱", 1);SupportTicket ticket2 = new SupportTicket("服务器异常", 113);// 处理者声明SupportHandler handler1 = new JuniorSupport();SupportHandler handler2 = new TechSupport();SupportHandler handler3 = new ManagerSupport();// 处理者链的组装handler1.setNextHandler(handler2);handler2.setNextHandler(handler3);// 问题处理的传递handler1.handleTicket(ticket1);handler1.handleTicket(ticket2);}
}
在 TestChain 中,我们创建了三个处理者(JuniorSupport、TechSupport、ManagerSupport),并将它们串联成一个处理链。当请求传递给第一个处理者时,若它不能处理请求,就将请求交给下一个处理者,直到找到合适的处理者或者到达链的末尾。
7. 总结
职责链模式通过将请求沿着处理者链进行传递,使得每个处理者只关心自己能处理的请求,从而减少了发送者与接收者之间的耦合。职责链模式有助于系统的灵活扩展,因为我们可以在运行时动态地调整处理链结构。通过这种模式,能够实现请求的逐层处理,直到有一个处理者能够处理该请求为止。
相关文章:
20 设计模式之职责链模式(问题处理案例)
一、什么是职责链模式 职责链模式是一种行为型设计模式,它允许将请求沿着处理者的链进行传递,直到有一个处理者能够处理它为止。换句话说,它将请求的发送者和接收者解耦,使得多个对象都有机会处理这个请求,从而避免了将…...
SpringBoot3集成MybatisPlus3和knife4j(swagger3兼容增强版)
针对Swagger2规范和OpenAPI3规范的说明: 在Spring Boot框架中,Knife4j对于服务端将Spring的开放接口解析成Swagger2或者OpenAPI3规范的框架,也是依赖的第三方框架组件。说明如下: Swagger2规范:依赖Springfox项目,该项目目前几乎处于停更状态,但很多老项目依然使用的是该…...
【MIT-OS6.S081作业1.3】Lab1-utilities primes
本文记录MIT-OS6.S081 Lab1 utilities 的primes函数的实现过程 文章目录 1. 作业要求primes (moderate)/(hard) 2. 实现过程2.1 代码实现 1. 作业要求 primes (moderate)/(hard) Write a concurrent version of prime sieve using pipes. This idea is due to Doug McIlroy, in…...
游戏引擎学习第35天
开场介绍 今天的任务是继续改进一个虚拟的瓦片地图系统,使其适合处理更大的世界。我们希望这个系统能管理大范围的游戏世界,其中包含按需存储的小区域。昨天,我们介绍了“内存区域”的概念,用于管理持久性存储。我们计划今天继续…...
learn-(Uni-app)输入框u-search父子组件与input输入框(防抖与搜索触发)
1.父子组件u-search (1)父组件 <!-- 父组件 --> <template> <div><searchBar change"change" search"search"></searchBar> </div> </template> <script> // 子组件搜索 import…...
设置IMX6ULL开发板的网卡IP的两种方法(临时生效和永久有效两种方法)
设置开发板网卡的IP,有两种方法。 方法一:临时生效 第一种方式是临时设置,只有本次有效,重启后又要重新设,命令为: ifconfig eth0 192.168.5.9设置成功后可以使用ifconfig命令来查看已设置的 IP 地址。 …...
流量转发利器之Burpsuite概述(1)
目录 一、Burpsuite Burp Suite Spider 的主要特点: 在 Burp Suite 中使用 Spider: Spider 的用例: 限制: 声明:学习视频来自b站up主 泷羽sec,如涉及侵权马上删除文章 声明:本文主要用作技…...
Transformer入门(6)Transformer编码器的前馈网络、加法和归一化模块
文章目录 7.前馈网络8.加法和归一化组件9.组合所有编码器组件构成完整编码器 7.前馈网络 编码器块中的前馈网络子层如下图所示: 图1.32 – 编码器块 前馈网络由两个带有ReLU激活函数的全连接层组成。全连接层(Fully Connected Layer)有时也…...
element-plus中的resetFields()方法
resetFields()确实是Element Plus中的方法,该方法主要用于重置表单,将其值重置为初始值,并移除校验结果。以下是对该方法的详细解释: 一、resetFields方法的作用 在Vue3结合Element Plus开发时࿰…...
【过滤器】.NET开源 ORM 框架 SqlSugar 系列
目录 0、 过滤器介绍 1、表过滤器 (推荐) 1.1 手动添加过滤器 1.2 禁用、清空、备份和还原 1.3 联表查询设置 1.4 动态添加 2、修改和删除用过滤器 2.1 局部设置 2.2 全局设置 (5.1.4.62) 3、子查询用过滤器 4、联表过滤…...
Jmeter Address already in use: connect 解决
做压测接口时,并发一段时间后,会报java.net.BindException: Address already in use: connect 原因: windows提供给TCP/IP链接的端口为 1024-5000,并且要四分钟来循环回收它们,就导致在短时间内跑大量的请求时将端口占…...
C#常见错误—空对象错误
System.NullReferenceException:未将对象引用设置到对象的实例 在C#编程中,System.NullReferenceException是一个常见的运行时异常,其错误信息“未将对象引用设置到对象的实例”意味着代码试图访问一个未被初始化或已被设置为null的对象的成…...
Leetcode数学部分笔记
Leetcode数学部分笔记 1. 回文数2. 加一3. 阶乘后的零4. x 的平方根5. Pow(x, n) 1. 回文数 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数 是指正序(从左向右)和倒序&…...
微信小程序web-view 嵌套h5界面 实现文件预览效果
实现方法:(这里我是在小程序里面单独加了一个页面用来下载预览文件) 安装 使用方法请参考文档 npm 安装 npm install weixin-js-sdk import wx from weixin-js-sdk预览 h5界面代码 <u-button click"onclick" type"primary" :loading"…...
【汽车】-- 燃油发动机3缸和4缸
3缸和4缸燃油发动机是小轿车常见的发动机配置。以下从结构特点、性能、经济性等方面对两者进行对比,并分析优缺点及使用注意事项: 1. 结构与运行原理 3缸发动机 特点:少一个气缸,内部零部件更少,整体结构更紧凑。优点…...
轻量级的 HTML 模板引擎
Mustache 简介:Mustache 是一个非常简单的逻辑少的模板引擎,支持 HTML 文件中的占位符替换。它不会执行复杂的逻辑,只支持简单的变量替换。 安装: npm install mustache示例: const Mustache require(mustache);c…...
Mysql | 尚硅谷 | 第02章_MySQL环境搭建
Mysql笔记:第02章_MySQL环境搭建 说明:本内容整理自尚硅谷B站MySQL视频>>尚硅谷B站MySQL视频 文章目录 Mysql笔记:第02章_MySQL环境搭建第02章_MySQL环境搭建 1. MySQL的卸载步骤1:停止MySQL服务步骤2:[软件](h…...
Maven学习(传统Jar包管理、Maven依赖管理(导入坐标)、快速下载指定jar包)
目录 一、传统Jar包管理。 (1)基本介绍。 (2)传统的Jar包导入方法。 1、手动寻找Jar包。并放置到指定目录下。 2、使用IDEA的库管理功能。 3、配置环境变量。 (3)传统的Jar包管理缺点。 二、Maven。 &#…...
CTF: 在本地虚拟机内部署CTF题目docker
step 1 安装基本依赖 sudo apt-get update sudo apt-get install -y \ca-certificates \curl \gnupg \lsb-releasestep 2 安装docker sudo apt-get remove docker docker.io containerd runc sudo apt-get update sudo apt-get install \apt-transport-https \ca-certificate…...
视频推拉流EasyDSS无人机直播技术巡查焚烧、烟火情况
焚烧作为一种常见的废弃物处理方式,往往会对环境造成严重污染。因此,减少焚烧、推广绿色能源和循环经济成为重要措施。通过加强森林防灭火队伍能力建设与长效机制建立,各地努力减少因焚烧引发的森林火灾,保护生态环境。 巡察烟火…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
