【设计模式】责任链模式

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

介绍

意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

何时使用:在处理消息的时候以过滤很多道。

如何解决:拦截的类都实现统一接口。

关键代码:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。

应用实例: 1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡。 3、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。

优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。

缺点: 1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。

使用场景: 1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求。

注意事项:在 JAVA WEB 中遇到很多应用。

实现

我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器消息的级别是否属于自己的级别,如果是则相应地打印出来,否则将不打印并把消息传给下一个记录器。

责任链模式的 UML 图

步骤 1

创建抽象的记录器类。

AbstractLogger.java

public abstract class AbstractLogger {public static int INFO = 1;public static int DEBUG = 2;public static int ERROR = 3;protected int level;//责任链中的下一个元素protected AbstractLogger nextLogger;public void setNextLogger(AbstractLogger 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);}

步骤 2

创建扩展了该记录器类的实体类。

ConsoleLogger.java

public class ConsoleLogger extends AbstractLogger {public ConsoleLogger(int level){this.level = level;}@Overrideprotected void write(String message) {    System.out.println("Standard Console::Logger: " + message);}
}

ErrorLogger.java

public class ErrorLogger extends AbstractLogger {public ErrorLogger(int level){this.level = level;}@Overrideprotected void write(String message) {    System.out.println("Error Console::Logger: " + message);}
}

FileLogger.java

public class FileLogger extends AbstractLogger {public FileLogger(int level){this.level = level;}@Overrideprotected void write(String message) {    System.out.println("File::Logger: " + message);}
}

步骤 3

创建不同类型的记录器。赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。每个记录器中的下一个记录器代表的是链的一部分。

ChainPatternDemo.java

public class ChainPatternDemo {private static AbstractLogger getChainOfLoggers(){AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);errorLogger.setNextLogger(fileLogger);fileLogger.setNextLogger(consoleLogger);return errorLogger;  }public static void main(String[] args) {AbstractLogger loggerChain = getChainOfLoggers();loggerChain.logMessage(AbstractLogger.INFO, "This is an information.");loggerChain.logMessage(AbstractLogger.DEBUG, "This is a debug level information.");loggerChain.logMessage(AbstractLogger.ERROR, "This is an error information.");}
}

步骤 4

执行程序,输出结果:

Standard Console::Logger: This is an information.
File::Logger: This is a debug level information.
Standard Console::Logger: This is a debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.

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

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

相关文章

腾讯云轻量应用服务器搭建WordPress网站教程

腾讯云百科分享使用腾讯云轻量应用服务器搭建WordPress网站教程流程&#xff0c;WordPress 是全球最流行的开源的博客和内容管理网站的建站平台&#xff0c;具备使用简单、功能强大、灵活可扩展的特点&#xff0c;提供丰富的主题插件。腾讯云轻量应用服务器提供 WordPress 应用…

C++:模拟实现list

文章目录 迭代器模拟实现 本篇模拟实现简单的list和一些其他注意的点 迭代器 如下所示是利用拷贝构造将一个链表中的数据挪动到另外一个链表中&#xff0c;构造两个相同的链表 list(const list<T>& lt) {emptyinit();for (auto e : lt){push_back(e);} }void test_…

二叉树(4)------收尾

1)最大二叉树 654. 最大二叉树 - 力扣&#xff08;LeetCode&#xff09; 题目解析: 1)首先我们找到了整个数组中最大的元素作为我们的根节点&#xff0c;然后再从左区间中找到最大的元素作为当前根节点的左子树&#xff0c;然后再从右区间里面找到最大的元素作为根节点的右子树…

8.10 用redis实现缓存功能和Spring Cache

什么是缓存? 缓存(Cache), 就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于本地代码。 通过Redis来缓存数据&#xff0c;减少数据库查询操作; 逻辑 每个分类的菜品保存一份缓存数据 数据库菜品数据有变更时清理缓存数据 如何将商品数据缓存起…

<Vite>HMR实现原理

什么是HMR&#xff1f; HMR&#xff08;Hot Module Replacement&#xff09;是一种开发工具&#xff0c;也就是热更新。用于在应用程序运行时替换、添加或删除模块&#xff0c;而无需完全重新加载整个页面或重新启动应用程序。这可以极大地提高开发效率和调试体验。 HMR的优势 …

JAVA日期相关操作

JAVA日期相关操作 计算两个日期相差的天数 /*** 计算两个日期相差的 天数* param smdate String类型初始时间* param bdate String类型截至时间* return Integer*/public static Integer dayCompare(String smdate, String bdate) throws Exception {Date start sdf.par…

深度学习快速入门系列---损失函数

在深度学习中&#xff0c;损失函数的作用是量化预测值和真实值之间的差异&#xff0c;使得网络模型可以朝着真实值的方向预测&#xff0c;损失函数通过衡量模型预测结果与真实标签之间的差异&#xff0c;反映模型的性能。同时损失函数作为一个可优化的目标函数&#xff0c;通过…

Ansible的安装和配置

安装和配置 Ansible 安装所需的软件包 创建名为 /home/greg/ansible/inventory 的静态清单文件&#xff0c;以满足以下要求&#xff1a; 172.25.250.9 是 dev 主机组的成员 172.25.250.10 是 test 主机组的成员 172.25.250.11 和 172.25.250.12 是 prod 主机组的成员 172.2…

解读spring中@Value 如何将配置转自定义的bean

实现方式 着急寻求解决方式的猿友先看这块 定义配置转化类 public class UserConverter implements Converter<String, List<User>> {Overridepublic List<User> convert(String config) {if (StringUtils.isEmpty(config)) {return Collections.emptyLis…

hive on tez资源控制

sql insert overwrite table dwintdata.dw_f_da_enterprise2 select * from dwintdata.dw_f_da_enterprise; hdfs文件大小数量展示 注意这里文件数有17个 共计321M 最后是划分为了21个task 为什么会有21个task&#xff1f;不是128M 64M 或者说我这里小于128 每个文件一个map…

从LeakCanary看Fragment生命周期监控

前文中我们已经了解到LeakCanary中Service生命销毁的监听方式&#xff0c;那么Fragment的生命周期监听又是怎么实现的呢&#xff1f; Activity生命周期监听&#xff0c;在Application里面有ActivityLifecycleCallbacks&#xff0c;那么Fragment是否相似呢&#xff1f;我们的第…

Linux 终端操作命令(2)内部命令

Linux 终端操作命令 也称Shell命令&#xff0c;是用户与操作系统内核进行交互的命令解释器&#xff0c;它接收用户输入的命令并将其传递给操作系统进行执行&#xff0c;可分为内部命令和外部命令。内部命令是Shell程序的一部分&#xff0c;而外部命令是独立于Shell的可执行程序…