设计模式笔记_行为型_责任链模式

1. 责任链模式介绍

责任链模式(Chain of Responsibility)是一种行为设计模式,它允许将多个处理器(处理对象)连接成一条链,并沿着这条链传递请求,直到有一个处理器处理它为止。职责链模式的主要目的是避免请求的发送者与多个请求处理者之间的耦合。

类比场景:想象一下,客户服务中心有多个层级的客服人员:初级客服、高级客服和经理。客户的问题会从初级客服开始,逐级向上转发,直到有一个客服能够解决问题。

组成结构:职责链模式主要包含以下几个部分:

  1. 抽象处理者(Handler):定义一个处理请求的接口,并包含一个指向下一个处理者的引用。
  2. 具体处理者(ConcreteHandler):实现处理请求的具体逻辑,并决定是否将请求传递给下一个处理者。
  3. 处理器链(HandlerChain): 在职责链模式的实现中,使用HandlerChain不是必须的,但是一种常见的做法。HandlerChain 的使用主要是为了简化链的管理,使得链的创建和维护更加便捷和集中。
  4. 客户端(Client):负责创建处理链,并向链中的第一个处理者发送请求。

优缺点分析:

  • 优点
    • 降低耦合:请求发送者和接收者之间的耦合度降低,灵活地新增和修改处理者。
    • 动态组合:可以方便地改变链内的成员或调动它们的次序。
  • 缺点
    • 不保证请求被处理:如果链的末端没有处理请求,可能会导致请求不被处理。这个场景可以通过责任链的变体实现,让请求被所有处理器都处理。
    • 性能问题:链过长可能导致性能问题,因为请求需要经过多个处理者。

适用场景:

  • 需要动态地指定请求的处理者。
  • 有多个对象可以处理某个请求,但具体处理者不确定。
  • 希望请求的发送者和接收者解耦。

2. 代码演示

责任链有链表列表两种实现方式,这里分别演示。演示场景围绕“初级客服、高级客服和经理处理客诉”展开。

2.1 链表实现

抽象处理者(Handler):链式实现方式中,抽象处理类是一个抽象类,里面定义了处理请求的接口(这里是doHandle接口),并包含指向下一个处理者的引用(这里对应nextHandler属性)。通常还会将调用下个处理器的通用逻辑提取出来(对应handleRequest方法),这样具体处理器类只需要实现自己的业务逻辑就可以了。

// 抽象处理者
public abstract class CustomerServiceHandler {//下一个处理器的对象protected CustomerServiceHandler nextHandler;public void setNextHandler(CustomerServiceHandler nextHandler) {this.nextHandler = nextHandler;}//调用下个处理器的逻辑,原本放在具体处理器中;属于通用逻辑,这里利用模版模式提取到父类public void handleRequest(String request) {boolean handled = doHandle(request);//gof定义:若当前处理器不能处理,则需要向下个处理器传递; 否则结束if (!handled && nextHandler != null) {nextHandler.handleRequest(request);}}//抽象处理逻辑:具体实现放在各handler自己实现的  doHandle() 函数里public abstract boolean doHandle(String request);}

具体处理者(ConcreteHandler):

//具体处理者 - 初级客服
public class JuniorCustomerService extends CustomerServiceHandler {@Overridepublic boolean doHandle(String request) {if (request.equals("basic")) {System.out.println("junior customer service handle");return true;}return false;}
}// 具体处理者 - 高级客服
public class SeniorCustomerService extends CustomerServiceHandler {@Overridepublic boolean doHandle(String request) {if (request.equals("advanced")) {System.out.println("senior customer service handle");return true;}return false;}
}// 具体处理者 - 经理
public class Manager extends CustomerServiceHandler {@Overridepublic boolean doHandle(String request) {if (request.equals("complex")) {System.out.println("manager customer service handle");return true;}return false;}
}

处理器链(HandlerChain):HandlerChain不是必须的,在某些情况下,直接在客户端代码中构建职责链是足够的,尤其是链简单且变化不频繁的时候。然而,在处理复杂链或需要动态调整链的场景下,引入 HandlerChain 可以提高代码的清晰度和灵活性。通过HandlerChain集中管理handlers,负责链中处理者的添加、移除和遍历,简化链的管理。

public class CustomerServiceHandlerChain {private CustomerServiceHandler firstHandler;private CustomerServiceHandler lastHandler;//给链表中添加处理器public void addHandler(CustomerServiceHandler handler) {if (firstHandler == null) {//链表头为null,放在链表头firstHandler = handler;lastHandler = handler;} else {//否则放在链表尾lastHandler.setNextHandler(handler);lastHandler = handler;}}//执行链表中的处理器:从第一个处理器开始执行public void handleRequest(String request) {if (null != firstHandler) {firstHandler.handleRequest(request);}}
}

客户端代码:

public class CustomerServiceChainDemo {public static void main(String[] args) {CustomerServiceHandlerChain handlerChain = new CustomerServiceHandlerChain();handlerChain.addHandler(new JuniorCustomerService());handlerChain.addHandler(new SeniorCustomerService());handlerChain.addHandler(new Manager());// 测试不同请求//handlerChain.handleRequest("basic");handlerChain.handleRequest("advanced");}
}

对应的类图:

2.2 列表实现

列表实现方式更加简单,与链表实现的差异点:

  • 抽象处理者(handler)改用interface (无需存储对下一个处理者的引用)
  • HandlerChain类中用列表而非链表来保存所有的处理器
  • 在HandlerChain中,依次调用每个handler(链表对nextHandler的调用放在抽象处理者类中)

抽象处理者(Handler):列表实现方式中,抽象处理者是一个接口,定义处理请求的方法。

//抽象处理者
public interface CustomerServiceHandler {boolean handlerRequest(String request);
}

具体处理者(ConcreteHandler):

//具体处理者 - 初级客服
public class JuniorCustomerService implements CustomerServiceHandler {@Overridepublic boolean handlerRequest(String request) {if (request.equals("basic")) {System.out.println("junior customer service handle");return true;}return false;}
}//具体处理者 - 高级客服
public class SeniorCustomerService implements CustomerServiceHandler {@Overridepublic boolean handlerRequest(String request) {if (request.equals("advanced")) {System.out.println("senior customer service handle");return true;}return false;}
}//具体处理者 - 经理
public class Manager implements CustomerServiceHandler {@Overridepublic boolean handlerRequest(String request) {if (request.equals("complex")) {System.out.println("manager customer service handle");return true;}return false;}
}

处理器链(HandlerChain):HandlerChain类中用列表而非链表来保存所有的处理器,并在HandlerChain的handle()函数中,依次调用每个处理器的handle()函数。

public class CustomerServiceHandlerChain {private List<CustomerServiceHandler> handlerList = new ArrayList<>();public void addHandler(CustomerServiceHandler handler) {handlerList.add(handler);}public void handleRequest(String request) {for (CustomerServiceHandler handler : handlerList) {//gof定义: 若当前处理器不能处理,则向下一个处理器传递; 否则结束Boolean handledResult = handler.handlerRequest(request);if (handledResult) {break;}}}
}

客户端代码:

public class CustomerServiceChainDemo {public static void main(String[] args) {CustomerServiceHandlerChain handlerChain = new CustomerServiceHandlerChain();handlerChain.addHandler(new JuniorCustomerService());handlerChain.addHandler(new SeniorCustomerService());handlerChain.addHandler(new Manager());// 测试不同请求handlerChain.handleRequest("basic");}
}

对应的类图:

2.3 变体:所有handler都处理一遍

上述实现是按照gof定义:如果处理器链上的某个处理器能够处理这个请求,那就不会继续往下传递请求,整个流程就会结束

职责链模式还有一种变体,那就是请求会被所有的处理器都处理一遍,不存在中途终止的情况。还是使用上述客服场景,假设用户需要退款,需要 初级/高级/经理 三级客服签字确认。

列表实现的代码如下:

//抽象处理者
public interface CustomerServiceHandler {void handlerRequest(String request);
}
//具体处理者 - 初级客服
public class JuniorCustomerService implements CustomerServiceHandler {@Overridepublic void handlerRequest(String request) {//doSomething ...System.out.println("junior customer service handle");}
}//具体处理者 - 高级客服
public class SeniorCustomerService implements CustomerServiceHandler {@Overridepublic void handlerRequest(String request) {//doSomething ...System.out.println("senior customer service handle");}
}//具体处理者 - 经理
public class Manager implements CustomerServiceHandler {@Overridepublic void handlerRequest(String request) {//doSomething ...System.out.println("manager customer service handle");}
}
//处理器链
public class CustomerServiceHandlerChain {private List<CustomerServiceHandler> handlerList = new ArrayList<>();public void addHandler(CustomerServiceHandler handler) {handlerList.add(handler);}public void handleRequest(String request) {for (CustomerServiceHandler handler : handlerList) {//变体类型: 不关注 handled值,请求会被所有的处理器都处理一遍,不存在中途终止的情况handler.handlerRequest(request);}}
}
//客户端代码
public class CustomerServiceChainDemo {public static void main(String[] args) {CustomerServiceHandlerChain handlerChain = new CustomerServiceHandlerChain();handlerChain.addHandler(new JuniorCustomerService());handlerChain.addHandler(new SeniorCustomerService());handlerChain.addHandler(new Manager());//发起退款handlerChain.handleRequest("退款100元");}
}

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

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

相关文章

pygame的帧处理中,涉及键盘的有`pg.event.get()`与`pg.key.get_pressed()` ,二者有什么区别与联系?

一、pg.event.get() 返回的是一组事件 pg.event.get() 返回的是一组事件&#xff08;一个包含多个事件对象的列表&#xff09;。这是因为在游戏的“一帧”时间内&#xff08;通常1/60秒左右&#xff09;&#xff0c;用户可能会触发多个事件&#xff08;比如同时按下多个键、快速…

TF - IDF算法面试与工作常见问题全解析

在自然语言处理领域&#xff0c;TF - IDF算法是一个基础且重要的概念。无论是在求职面试还是在实际工作中&#xff0c;都经常会遇到与TF - IDF相关的问题。以下是一些常见的问题及其详细解答&#xff1a; 一、基本概念类问题 1. 什么是TF - IDF算法&#xff1f; TF - IDF&#…

Transformer网络结构解析

博主会经常分享自己在人工智能阶段的学习笔记&#xff0c;欢迎大家访问我滴个人博客&#xff01;&#xff08;都不白来&#xff01;&#xff09; 小牛壮士 - 个人博客https://kukudelin.top/ 前言 Transformer 广泛应用于自然语言处理&#xff08;如机器翻译、文本生成&…

gateway进行接口日志打印

打印需求&#xff1a;对所有的接口打印&#xff1a;请求方式&#xff0c;请求路径&#xff0c;请求参数&#xff0c;用户id&#xff0c;访问IP&#xff0c;访问时间对增删改操作的接口打印&#xff1a;接口响应打印方案&#xff1a;给GET设置一个白名单&#xff08;因为get请求…

MATLAB实现图像增强(直方图均衡化)

直方图均衡化是一种常用的图像增强技术&#xff0c;它通过重新分布图像的像素强度值来增强图像的对比度。以下是MATLAB中实现直方图均衡化的详细方法。%% 直方图均衡变换 clc;close all;clear all;warning off;%清除变量 rand(seed, 100); randn(seed, 100); format long g;%% …

java15学习笔记-密封类

360:Sealed Classes (Preview) 封闭类&#xff08;预览&#xff09; 总结 使用密封类和接口增强Java编程语言。密封类和接口限制了哪些其他类或接口可以扩展或实现它们。这是JDK 15中的预览语言功能。 目标 允许类或接口的作者控制负责实现它的代码。 提供一种比访问…

西门子PLC通过稳联技术EtherCAT转Profinet网关连接baumuller伺服器的配置案例

西门子PLC用稳联技术的EtherCAT转Profinet网关&#xff0c;连上baumuller伺服器的配置例子本案例实现西门子S71200 PLC通过EtherCAT转Profinet网关对baumuller&#xff08;Baumller&#xff09;伺服器的实时控制&#xff0c;适用于高精度运动控制场景&#xff08;如精密机床、自…

Ansible 详细笔记

Ansible 详细笔记 一、Ansible 基础概述 1.1 定义与定位 Ansible 是由 Red Hat 主导开发的开源自动化运维工具&#xff0c;基于 Python 语言实现&#xff0c;专注于简化 IT 基础设施的配置管理、应用部署、任务编排等操作。它采用无代理架构&#xff0c;通过 SSH 协议与被控节点…

【Java 后端】Spring Boot 集成 JPA 全攻略

Spring Boot 集成 JPA 全攻略 一、前言 在 Java Web 开发中&#xff0c;数据库访问是绕不开的话题。 传统方式使用 JDBC 编写 SQL&#xff0c;维护困难、可读性差。后来有了 MyBatis 这种半自动 ORM 框架&#xff0c;再到 JPA&#xff08;Java Persistence API&#xff09;这…

pytorch学习笔记-加载现有的网络模型(VGG16)、增加/修改其中的网络层(修改为10分类)

写在前面&#xff1a;有些地方和视频里不一样的是因为官方文档更新了&#xff0c;一些参数用法不一样也很正常&#xff0c;包括我现在的也是我这个时间节点最新的&#xff0c;谁知道过段时间会不会更新呢 建议大家不要一味看视频/博客&#xff0c;多看看官方文档才是正道&#…

RocketMQ 4.9.3源码解读-NameServer组件启动流程分析

作者源码阅读笔记主要采用金山云文档记录的,所有的交互图和代码阅读笔记都是记录在云文档里面,本平台的文档编辑实在不方便,会导致我梳理的交互图和文档失去原来的格式,所以整理在文档里面,供大家阅读交流 【金山文档 | WPS云文档】 namesrv 启动流程 相关重要类介绍说明…

《嵌入式 C 语言编码规范与工程实践个人笔记》参考华为C语言规范标准

《嵌入式 C 语言编码规范与工程实践个人笔记》参考华为C语言规范标准 前言 在电子系统开发领域&#xff0c;C 语言作为底层开发的核心语言&#xff0c;其代码质量直接关系到系统的稳定性、可维护性和扩展性。良好的编码规范不仅是团队协作的基础&#xff0c;更是降低生命周期成…

纯半精度模型和全精度模型的耗时分别为248微秒和1400微秒。混合精度模型371微秒比原始模型快大约四倍!

不过有一点需要注意:在上下文管理器内部生成的任何输出,必然会采用该上下文管理器的数据类型。因此,之后我们必须将这些输出转换回FP32(例如,使用float()函数)。 with torch.autocast(device_type="cuda", dtype=torch.float16): res16 = mixed32(torch.randn…

一款开源的远程桌面软件,旨在为用户提供流畅的游戏体验,支持 2K 分辨率、60 FPS,延迟仅为 40ms。

软件介绍 CloudPlayPlus&#xff08;云玩加&#xff09;是一款令人惊艳的开源远程桌面、串流软件&#xff0c;云玩加由个人开发者开发者&#xff0c;具有四大特征&#xff1a;开源、免费、低延迟、安全。 软件使用 客户端支持多个平台&#xff0c;包括 Windows、Mac OS、安卓…

MySql——binlog和redolog的区别

目录一、binlog和redolog的区别一、binlog和redolog的区别 binlog和redolog都是存储修改的新数据&#xff0c;是否保留binlog和redolog中的一个即可。 binlog属于整个mysql&#xff0c;是所有引擎共用的&#xff0c;不是只属于innoDB引擎。而redolog属于InnoDB存储引擎。binlo…

软件著作权产生与登记关键点

知识讲解一、 软件著作权的核心特征与权利内容自动产生原则&#xff1a; 这是软件著作权最核心、最重要的特征。产生时间&#xff1a; 软件著作权自软件开发完成之日起自动产生。法律依据&#xff1a; 《中华人民共和国著作权法》第二条及《计算机软件保护条例》第五条明确规定…

什么是主成分分析(PCA)和数据降维

主成分分析&#xff08;PCA&#xff09;和数据降维是机器学习和统计学中处理高维数据的核心工具。下面用清晰的结构解释其概念、原理和应用&#xff1a; 一、数据降维&#xff08;Dimensionality Reduction&#xff09; 1. 是什么&#xff1f; 目标&#xff1a;将高维数据&…

图论(4)单源赋权最短路径算法实现(BFS实现)

目录 1. 什么是赋权最短路径 2. 赋权最短路径中的关键概念 3. Dijkstra 算法的基本思想 4. Dijkstra 算法实现&#xff08;Java&#xff09; 1. 什么是赋权最短路径 在图论中&#xff0c;最短路径问题是指在图中寻找两点之间路径总权重最小的路径问题。如果图的每条边都带…

【Lua】题目小练9

题目&#xff1a;实现一个简单的“银行账户”类要求&#xff1a;使用 元表 模拟面向对象。支持以下功能&#xff1a;Account:new(owner, balance) 创建账户&#xff08;初始余额可选&#xff0c;默认为 0&#xff09;。deposit(amount) 存款&#xff08;不能为负数&#xff09;…

【二分图】染色问题

核心思想&#xff1a;为每一个未染色的&#xff0c;对它自己和它的邻居进行染色&#xff0c;看是否会出现冲突时间复杂度O&#xff08;nm&#xff09;#include<bits/stdc.h> using namespace std; using lllong long; const int N200010; int n,m; vector<int>edge…