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 中,我们创建了三个处理者(JuniorSupportTechSupportManagerSupport),并将它们串联成一个处理链。当请求传递给第一个处理者时,若它不能处理请求,就将请求交给下一个处理者,直到找到合适的处理者或者到达链的末尾。

7. 总结

        职责链模式通过将请求沿着处理者链进行传递,使得每个处理者只关心自己能处理的请求,从而减少了发送者与接收者之间的耦合。职责链模式有助于系统的灵活扩展,因为我们可以在运行时动态地调整处理链结构。通过这种模式,能够实现请求的逐层处理,直到有一个处理者能够处理该请求为止。

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

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

相关文章

linux基于systemd自启守护进程 systemctl自定义服务傻瓜式教程

系统服务 书接上文: linux自启任务详解 演示系统:ubuntu 20.04 开发部署项目的时候常常有这样的场景: 业务功能以后台服务的形式提供,部署完成后可以随着系统的重启而自动启动;服务异常挂掉后可以再次拉起 这个功能在ubuntu系统中通常由systemd提供 如果仅仅需要达成上述的场…

ros项目dual_arm_pick-place(moveit和gazebo联合仿真)(一)

目录 前言正文创建功能包具体代码运行 总结 前言 dual_arm_pick-place项目中&#xff0c;实现了两套的moveit和gazebo联合仿真。 启动文件分别是bringup_moveit.launch和arm_bringup_moveit.launch。 在这个项目中&#xff0c;我将代码重新创建了一个包&#xff0c;co_simula…

MySQL 索引(B+树)详解

MySQL 索引&#xff08;B树&#xff09;详解 MySQL逻辑架构对比InnoDB与MyISAM存储结构存储空间可移植性、备份及恢复事务支持AUTO_INCREMENT表锁差异全文索引表主键表的具体行数CRUD操作外键 sql优化简介什么情况下进行sql优化sql语句执行过程sql优化就是优化索引 索引索引的优…

MySQL生产环境备份脚本

全量备份脚本&#xff0c;其中BakDir&#xff0c;ZlbakDir&#xff0c;LogFile需要自己创建 #!/bin/bash export LANGen_US.UTF-8# 指定备份目录 BakDir/root/beifen/data/mysqlbak/data/allbak # 指定增量备份目录 ZlbakDir/root/beifen/data/mysqlbak/data/zlbak # 备份日志…

HTTP multipart/form-data 请求

序言 最近在写项目的过程中有一个需求是利用 HTTP 协议传输图片和视频&#xff0c;经过查询方法相应的方法发现使用 multipart/form-data 的方式&#xff0c;这是最常见处理二进制文件的表单编码类型。  学习了一下午&#xff0c;现在总结一下使用的方法和相关的知识点&#x…

Linux下redis环境的搭建

1.redis的下载 redis官网下载redis的linux压缩包&#xff0c;官网地址:Redis下载 网盘链接&#xff1a; 通过网盘分享的文件&#xff1a;redis-5.0.4.tar.gz 链接: https://pan.baidu.com/s/1cz3ifYrDcHWZXmT1fNzBrQ?pwdehgj 提取码: ehgj 2.redis安装与配置 将包上传到 /…

如何使用靜態IP代理?【詳細教程】

靜態IP地址是手動分配給設備或伺服器的固定不變的 IP。與動態 IP 地址不同&#xff0c;動態 IP 地址由 DHCP 伺服器自動分配&#xff0c;並且會隨時間而變化。​​​​​​​ 如何獲取和設置靜態IP地址 一、檢查是否需要靜態IP&#xff1f; 在配置靜態 IP 之前&#xff0c;請…

监控组态软件的构成与功能

监控组态软件的构成包括系统开发环境、图形界面系统、实时数据库系统等。其功能包括数据采集与控制、人机交互界面、数据处理与存储等。 监控组态软件的构成&#xff1a; 系统开发环境&#xff1a;这是自动化工程设计工程师为实施其控制方案&#xff0c;在组态软件的支持下进行…

Java 基础之 XQuery:强大的 XML 查询语言

一、什么是 XQuery XQuery 是一种函数式语言&#xff0c;专门用于检索以 XML 格式存储的信息。它负责从 XML 文档中查找和提取元素及属性&#xff0c;在网络服务中有着广泛的应用&#xff0c;比如提取信息、生成摘要报告、进行数据转换等。 XQuery 是 W3C 设计的一种针对于 X…

day09性能测试(1)——纯理论

document.querySelector(video).playbackRate 2.5 //可以写任何数字 【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 1、性能测试概念 2、功能测试 vs 性能测试 3、小结&#xff08;习题&#xff09; 4、性能测试的策略 4.1 基准测试 4.2 负载测试 …

docker-3.docker权限问题

docker权限,每次开机都要重新sudo 目录 1.简介2.解决办法1:当前用户添加到docker用户组(这个方法还是缺权限??)3.解决办法2:临时更改Docker socket文件权限1.简介 Ubuntu下Docker提示permission denied (权限不足)解决办法 安装docker后,执行docker ps命令时提示 perm…

easyExcel实现表头批注

背景&#xff1a; 网上大部分都不能直接使用&#xff0c;为此总结一个方便入手且可用的工具&#xff0c;用自定义注解实现 依赖包&#xff1a; <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>…

内部类和Object类

匿名对象 格式&#xff1a; 匿名对象只可以调用一次成员 &#xff1a; 1. 调用一次成员变量 &#xff1a; new 类名(实参).成员变量名&#xff1b; 2.调用一次成员方法&#xff1a; new 类名(实参).成员方法名(实参)&#xff1b; 匿名对象存在的必要&#xff1a;为了提高…

Python的3D可视化库vedo 1-3 (visual模块)网格对象的线和面、图片的属性

文章目录 4 MeshVisual4.1 线条4.1.1 线宽和颜色4.1.2 线条渲染为管 4.2 曲面4.2.1 物体展示为实心或框架4.2.2 曲面插值4.2.3 面的剔除 4.3 纹理4.4 相机跟随 5 ImageVisual5.1 图片属性5.1.1 占用内存大小5.1.2 颜色标量范围 5.2 渲染属性5.2.1 透明度5.2.2 亮度5.2.3 对比度…

19 设计模式之享元模式(电影院座位预定案例)

一、享元模式的定义 享元模式是一种结构型设计模式&#xff0c;它通过共享对象来支持大量细粒度的对象&#xff0c;减少内存消耗。享元模式的核心思想是&#xff1a;将对象分为共享部分和非共享部分&#xff0c;只有共享部分是被多个对象共享的&#xff0c;而非共享部分则是每个…

使用redis 的stream 做消息中间件 多线程消费消息

1.redis stream 特点 1.支持消息持久化 2.消费者组模式 3.消息确认机制 4. 消息重试机制 5. 死信队列2. 消息生产者服务 2.1 如下代码Service Slf4j public class StreamMessageProducer {Autowiredprivate StringRedisTemplate redisTemplate;private static final String S…

Python100道练习题

Python100道练习题 BIlibili 1、两数之和 num1 20 num2 22result num1 num2print(result)2、一百以内的偶数 list1 []for i in range(1,100):if i % 2 0:list1.append(i) print(list1)3、一百以内的奇数 # 方法一 list1 [] for i in range(1,100):if i % 2 ! 0:lis…

Java转C之并发和多线程

提纲&#xff1a; 概念介绍与对比概述 简述Java与C在并发和多线程方面的核心区别解释C11标准、POSIX、C11 <threads.h>、Pthread等名词 Java多线程与并发回顾 线程、Runnable、ExecutorService概念说明同步关键字与工具类含义 C并发基础 没有Java式的内置线程类&#xf…

Ubuntu系统本地化搭建Maxakb+Ollama

安装docker 最详细的ubuntu 安装 docker教程-腾讯云开发者社区-腾讯云 安装Ollama Ollama官网 执行命令&#xff1a; curl -fsSL https://ollama.com/install.sh | sh安装完成后下载模型 执行命令&#xff1a; ollama run llama3.3:70b安装MaxKb 执行命令&#xff1a; d…

基于JAVA的旅游网站系统设计

摘要 随着信息技术和网络技术的迅速发展&#xff0c;人们的生活质量和观念也在发生着改变&#xff0c;各地争相发展旅游业&#xff0c;传统的 旅游社已经无法满足人们的需求&#xff0c;旅游网站将突破传统在时间和地域的限制&#xff0c;成为方便、快捷、安全、可靠的旅游 方…