责任链模式 (Chain of Responsibility Pattern)

定义

责任链模式是一种行为型设计模式,用于在对象间建立一条处理请求的链。它允许多个对象有机会处理请求,从而减少请求的发送者和接收者之间的耦合。在责任链模式中,每个接收者包含对另一个接收者的引用,形成一条链。如果一个对象不能处理请求,它会将请求传递给链中的下一个对象,直至链的末端。

责任链模式由多个处理器(或接收者)组成,每个处理器决定自己是否处理请求或将其传递给链上的下一个处理器。这种模式实现了发送者和接收者之间的解耦,同时允许动态地调整链中的处理器。

责任链模式主要包含以下两个角色:

  1. 处理器(Handler)
    • 定义了处理请求的接口或抽象类,并通常持有对下一个处理器的引用。在其子类中,它可以选择处理请求或将请求传递给链上的下一个对象。
  2. 具体处理器(Concrete Handler)
    • 实现处理器接口的具体类。每个具体处理器决定它是否要处理请求,如果不处理,则将请求传递给链中的下一个对象。
解决的问题
  • 请求的发送者和接收者解耦
    • 在没有责任链模式的情况下,请求的发送者需要知道哪个接收者能够处理该请求,并直接调用相应的处理方法。责任链模式使得请求的发送者不需要直接与具体的接收者交互,从而解耦了发送者和接收者。
  • 动态处理请求
    • 责任链模式允许动态地重新组织和分配责任链上的处理者。这意味着可以在运行时改变请求的处理顺序或者增加新的处理者。
  • 简化对象间的连接
    • 通过责任链,可以减少对象间复杂的条件语句。在责任链模式中,请求沿着链传递,直到被处理。这避免了显式的多重条件判断。
  • 增加处理者的灵活性
    • 责任链模式让每个处理者都有机会处理请求。处理者可以决定是否处理请求,或者将请求传递给链上的下一个对象。
  • 分布式责任
    • 责任链模式允许多个对象处理请求,而不是只有一个对象负责所有的情况。这种分布式责任有助于代码的复用和扩展。
使用场景
  • 多个对象可以处理同一个请求,但具体的处理者在运行时才确定
    • 当一个请求可能由多个不同的对象处理,但是具体由哪个对象处理在运行时才决定时,责任链模式是理想的解决方案。
  • 请求的发送者不需要知道是谁处理了请求
    • 如果请求的发送者不需要知道请求最终由哪个对象处理,责任链模式可以将请求的发送和处理解耦。
  • 动态指定一组对象处理请求
    • 当需要动态地指定一系列对象来处理请求时,责任链模式提供了一种灵活的方法来组织这些对象。
  • 实现不同方式的请求处理
    • 在有多种处理方式,并且希望根据请求的类型或条件以不同的方式处理时,责任链模式能够提供足够的灵活性。
示例代码1-日志处理器
// 抽象处理器类
public abstract class Logger {public static int INFO = 1;public static int DEBUG = 2;public static int ERROR = 3;protected int level;protected Logger nextLogger;public void setNextLogger(Logger nextLogger) {this.nextLogger = nextLogger;}public void logMessage(int level, String message) {if (this.level <= level) {write(message);}if (nextLogger != null) {nextLogger.logMessage(level, message);}}abstract protected void write(String message);
}// 具体处理器实现
class ConsoleLogger extends Logger {public ConsoleLogger(int level) {this.level = level;}@Overrideprotected void write(String message) {        System.out.println("Standard Console::Logger: " + message);}
}// 客户端使用责任链
public class ChainPatternDemo {private static Logger getChainOfLoggers() {Logger errorLogger = new ErrorLogger(Logger.ERROR);Logger fileLogger = new FileLogger(Logger.DEBUG);Logger consoleLogger = new ConsoleLogger(Logger.INFO);errorLogger.setNextLogger(fileLogger);fileLogger.setNextLogger(consoleLogger);return errorLogger;}public static void main(String[] args) {Logger loggerChain = getChainOfLoggers();loggerChain.logMessage(Logger.INFO, "This is an information.");loggerChain.logMessage(Logger.DEBUG, "This is a debug level information.");loggerChain.logMessage(Logger.ERROR, "This is an error information.");}
}
示例代码2-审批流程
// 抽象处理器
abstract class Approver {protected Approver successor;public void setSuccessor(Approver successor) {this.successor = successor;}public abstract void processRequest(PurchaseRequest request);
}// 具体处理器:经理
class Manager extends Approver {public void processRequest(PurchaseRequest request) {if (request.getAmount() < 1000) {System.out.println("Manager will approve the request of " + request.getAmount());} else if (successor != null) {successor.processRequest(request);}}
}// 具体处理器:总监
class Director extends Approver {public void processRequest(PurchaseRequest request) {if (request.getAmount() < 5000) {System.out.println("Director will approve the request of " + request.getAmount());} else if (successor != null) {successor.processRequest(request);}}
}// 具体处理器:CEO
class CEO extends Approver {public void processRequest(PurchaseRequest request) {if (request.getAmount() < 10000) {System.out.println("CEO will approve the request of " + request.getAmount());} else {System.out.println("Request of " + request.getAmount() + " needs a board meeting!");}}
}// 请求类
class PurchaseRequest {private double amount;public PurchaseRequest(double amount) {this.amount = amount;}public double getAmount() {return amount;}
}// 客户端代码
public class ChainOfResponsibilityDemo {public static void main(String[] args) {Approver manager = new Manager();Approver director = new Director();Approver ceo = new CEO();manager.setSuccessor(director);director.setSuccessor(ceo);manager.processRequest(new PurchaseRequest(500));manager.processRequest(new PurchaseRequest(1500));manager.processRequest(new PurchaseRequest(5500));}
}
主要符合的设计原则
  • 开闭原则(Open-Closed Principle)
    • 责任链模式允许在不修改现有代码的情况下添加新的处理器。你可以添加新的处理类来扩展系统的功能,而无需修改现有的处理链或客户端代码。因此,系统对扩展是开放的,但对修改是封闭的。
  • 单一职责原则(Single Responsibility Principle)
    • 在责任链模式中,每个处理器只负责处理特定类型的请求。这符合单一职责原则,因为每个处理器类只有一个理由发生变化——处理其特定的请求。
  • 里氏替换原则(Liskov Substitution Principle)
    • 责任链中的处理器通常遵循相同的接口。这意味着处理器的任何子类都可以替换其父类,而不影响系统的行为。
在JDK中的应用
  • java.util.logging.Logger
    • java.util.logging 包中,Logger 类使用责任链模式。日志消息可以在一个日志处理链中传递,每个处理器(如 ConsoleHandler, FileHandler)决定是否处理日志消息,并将消息传递到链中的下一个处理器。
  • Java Servlet Filters
    • 在Java Servlet API中,过滤器(Filter)使用责任链模式。请求和响应在多个过滤器之间传递,每个过滤器可以独立地处理请求或响应,或将其传递给链中的下一个过滤器。
  • javax.servlet.FilterChain
    • FilterChain 是Servlet API的一部分,它允许多个过滤器按顺序处理HTTP请求和响应。每个过滤器在链中都有机会处理请求和响应,或将其传递给链上的下一个过滤器。
在Spring中的应用
  • Spring Security的过滤器链
    • 在Spring Security中,安全过滤器链是责任链模式的一个显著例子。请求通过一系列的安全过滤器,每个过滤器执行特定的安全检查(如认证、授权等)。这些过滤器可以自定义和配置,形成一个处理安全的责任链。
  • Spring Web的拦截器
    • 在Spring MVC中,拦截器(Interceptor)提供了一种在处理HTTP请求时插入自定义逻辑的机制。拦截器可以形成一个拦截器链,每个拦截器按顺序执行,处理请求或响应,或将控制权传递给链中的下一个拦截器。
  • Spring AOP的通知链
    • 在Spring的面向切面编程(AOP)中,通知(Advice)可以被看作是责任链的一部分。不同的通知(如前置通知、后置通知、环绕通知等)可以按顺序应用于方法调用,形成一个通知链。

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

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

相关文章

tcp和 udp区别

相同点&#xff1a;都是传输层协议 不同点 是否面向连接 tcp:面向连接 三次握手&#xff0c;四次挥手端对端连接全双工通信&#xff08;允许双端同时收发数据&#xff09; udp:无连接 无三次握手&#xff0c;四次挥手支持一对一,一对多&#xff0c;多对多 数据传输方式 …

Linux平台下使用.NET Core访问Access数据库

运行环境 操作系统&#xff1a;Ubuntu 22.04.3 LTS (Jammy)开发工具&#xff1a;Visual Studio 2022 (17.8.0)运行时版本&#xff1a;.NET Runtime 8.0依赖库&#xff1a;unixodbc、mdbtools、odbc-mdbtools 依赖库安装 apt-get update sudo apt-get install unixodbc mdbto…

部署项目时常用的 Linux 命令

目录 1 前言2 SSH登录命令3 SCP传输命令4 CP拷贝命令5 MV移动命令6 TAR解压命令7 DU查看文件夹/文件大小8 TAIL查看日志9 NOHUP后台运行10 结语 1 前言 在应用部署过程中&#xff0c;Linux命令是必不可少的工具。它们能够帮助我们管理文件、连接服务器、拷贝文件、查看日志以及…

vite项目配置vite.config.ts在打包过程中去除日志

在生产环境上&#xff0c;务必要将日志清除干净&#xff0c;其因有二&#xff0c;在webgis系统中&#xff0c;有很多几何数据&#xff0c;体积大、数量多&#xff0c;很容易引起系统卡顿&#xff1b;清除log后&#xff0c;系统看着舒服&#xff0c;协同开发有很多无聊的日志&am…

生日礼物——华为机考真题

题目描述 小牛的孩子生日快要到了&#xff0c;他打算给孩子买蛋糕和小礼物&#xff0c;蛋糕和小礼物各买一个&#xff0c; 他的预算不超过x元。蛋糕 Cake 和小礼物 gift 都有多种价位的可供选择。 请返回小牛共有多少种购买方案。 输入描述 第一行表示 Cake的单价, 以逗号分隔 …

字符串:leetcode1410. HTML 实体解析器

1410. HTML 实体解析器 「HTML 实体解析器」 是一种特殊的解析器&#xff0c;它将 HTML 代码作为输入&#xff0c;并用字符本身替换掉所有这些特殊的字符实体。 HTML 里这些特殊字符和它们对应的字符实体包括&#xff1a; 双引号&#xff1a;字符实体为 &quot; &#xff…

一款非常优秀的项目管理工具:进度猫(推荐)

在项目管理中&#xff0c;一个好的工具可以极大地提高效率。 进度猫是一款非常优秀的项目管理工具。它具有非常强大的功能&#xff0c;可以帮助团队更好地管理项目进度。 通过可视化的方式&#xff0c;将项目进度、任务分配、需求变更等全面呈现给团队成员&#xff0c;让团队…

5.过滤敏感词 + 发布帖子 + 帖子详情

目录 1.过滤敏感词 1.1 定义前缀树 1.2 根据敏感词,初始化前缀树 1.3 编写过滤敏感词方法

需求分析BSA法

&#x1f449;BSA法&#xff08;Basic–Satisfier–Attractor&#xff09;是对客户需求进行优先级划分的需求分析方法。该模型体现了需求满足度和客户满意度之间的非线性关系。BSA法将客户需求分为3种类型&#xff0c;分别是基本型需求、满意型需求和兴奋型需求。下面将对每种需…

ABB机 器 人 操 作 培 训

目 录 1 培训手册介绍 ---------------------------------------------2 2 系统安全与环境保护 ---------------------------------------------3 3 机器人综述 ---------------------------------------------5 4 机器人示教 --------------------------------------------12…

哲学家就餐问题(java全代码)

题目 有N个哲学家围坐在一张圆桌旁&#xff0c;桌上只有N把叉子&#xff0c;每对哲学家中间各有一把。 哲学家的两种行为&#xff1a; 一、思考 二、吃意大利面 哲学家只能拿起手边左边或右边的叉子 吃饭需要两把叉子 正确地模仿哲学家的行为 方法一 一次只允许四个人…

FSCTF2023-Reverse方向题解WP。学习贴

文章目录 [FSCTF 2023]signin[FSCTF 2023]MINE SWEEPER[FSCTF 2023]Xor[FSCTF 2023]EZRC4[FSCTF 2023]ez_pycxor[FSCTF 2023]Tea_apk[FSCTF 2023]ezcode[FSCTF 2023]ezbroke[FSCTF 2023]rrrrust!!![FSCTF2023]ezrev&#xff08;未解决&#xff09; [FSCTF 2023]signin UPX壳&am…

redis-cluster集群模式

Redis-cluster集群 1 Redis3.0引入的分布式存储方案 2集群由多个node节点组成,redis数据分布在节点之中,在集群之中分为主节点和从节点3集群模式当中,主从一一对应,数据写入和读取与主从模式一样&#xff0c;主负责写&#xff0c;从只能读4集群模式自带哨兵模式&#xff0c;可…

自然资源土地管理法律法规知识竞赛这么办才高端

近些年&#xff0c;全国各地自然资源厅举办了土地管理法律法规知识竞赛&#xff0c;从我公司承办的这些赛事来看&#xff0c;传统的必答题、抢答题、风险题的方式已无法激起现场比赛气氛&#xff0c;需要更加复杂有趣的环节设置及高端竞赛软件及其配套设备加持才可以让知识竞赛…

Eigen::Matrix 转 std::vector 亲测ok!

std::vector<double> data;for (int kk 0; kk < 24; kk) {data.push_back(kk);}int n 24 / 3;typedef Eigen::Matrix<double, 3, Eigen::Dynamic> MatrixXd;//vector 转 matrixEigen::Map<Eigen::MatrixXd> result(data.data(), 3, n);//matrix 转 vect…

什么是交易量价差分析法?anzo Capital一分钟讲明白

交易量价差分析法是一种深入的市场分析方法&#xff0c;它主要探讨了价格、价差和交易量之间的相互关系。在此过程中&#xff0c;交易量主要揭示了市场上的交易活动情况&#xff0c;而价差则反映了这些交易的价格变动。 为了更准确地理解这种关系&#xff0c;定义了交易量价差…

21. Spring扩展点之推断构造方法

简介 spring自己本身有推断构造方法的逻辑&#xff0c;但同时也提供了扩展&#xff0c;SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors&#xff0c;实现该方法就可以自己定制获取哪个构造器的逻辑&#xff0c;该扩展点spring有一个默认的实现Autow…

单元测试-java.lang.NullPointerException

报错信息 java.lang.NullPointerException 空指针异常 空对象引用 来源 对Controller层进行单元测试&#xff0c;解决完Spring上下文报错后继续报错。 解决 在测试方法执行前要为字段完成对象的注入&#xff0c;否则就报空指针异常。 测试例子 public class SysUserContr…

前端css粘性布局,顶部吸附效果(position: sticky)

sticky属性设置 /* 设置粘性布局 */ position: sticky; /* 拖动滚动条&#xff0c;当前元素超出文档0的位置时&#xff0c;触发定位效果&#xff08;同级元素位置不会受影响&#xff09; */ top: 0;页面初始效果 设置前&#xff08;滚动页面时&#xff0c;标签栏随页面滚动&a…

【深度学习】六大聚类算法快速了解

在机器学习中&#xff0c;无监督学习一直是我们追求的方向&#xff0c;而其中的聚类算法更是发现隐藏数据结构与知识的有效手段。目前如谷歌新闻等很多应用都将聚类算法作为主要的实现手段&#xff0c;它们能利用大量的未标注数据构建强大的主题聚类。本文从最基础的 K 均值聚类…