前言
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情。
🍊作者简介: 不肯过江东丶,一个来自二线城市的程序员,致力于用“猥琐”办法解决繁琐问题,让复杂的问题变得通俗易懂。
🍊支持作者: 点赞👍、关注💖、留言💌~
大聪明在写代码的过程中发现设计模式的影子是无处不在,设计模式也是软件开发人员在软件开发过程中面临的一般问题的解决方案。大聪明本着“独乐乐不如众乐乐”的宗旨与大家分享一下设计模式的学习心得。
责任链模式
🍓🍓什么是责任链模式🍓🍓
在讲责任链模式之前,我们先来看一下它的定义👇
责任链模式(Chain of Responsibility Pattern),顾名思义,它为请求创建了一个接收者对象的链。为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链,当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。(责任链模式也叫职责链模式)
通俗点来说,它为了保证让多个对象都有可能接收请求,于是就将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止,同时实现了请求发送者与请求接收者直接的解耦。(请求发送者只需要将请求发送到责任链上即可,无须关心请求的处理细节和请求的传递过程,请求会自动进行传递,即实现了二者之间的解耦)
这就有点像一句俗话 —— “大懒支小懒”,包工头接到了一份搬砖的工作,于是就把工作分配给了大懒,大懒想:搬砖这么累,我才不干呢,给下面的人分配去,总会有人干的😎!于是就将任务分配给小懒;小懒如果也不想干的话,就将任务继续分配给小小懒... 直到任务分配给了小小小...小懒,他才尽心尽力的搬完了砖(心疼他三秒钟🙁),也就让包工头赚到了钱。在这个例子中,搬砖的工作就是请求;包工头就是请求的发送者;大懒 → 小懒 → ... → 小小小...小懒为请求接受者链,这就是一个很形象的责任链模式的体现✌。
🍋 说实话,我总感觉责任链模式的本质和递归的本质有点相似,有兴趣的小伙伴可以移步至大聪明教你学Java | 深入浅出聊递归(以汉诺塔为例)
通过上面的例子,我们可以总结出来责任链模式中的三个角色:
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
🍓🍓责任链模式的实现🍓🍓
🍋责任链模式实现背景: 我们在开发应用系统的过程中,经常会遇到记录日志的需求。日志分为三种类型,分别是INFO(消息)、DEBUG(调试) 、ERROR(报错),当需要记录日志的时候,通过判断看看日志属于哪种类型, 然后对应的日志处理类再去处理相应的日志信息。
🍎🍎创建抽象的日志记录器类🍎🍎
/**
* 抽象的日志记录器类
* @description: AbstractLogger
* @author: 庄霸.liziye
* @create: 2022-04-16 07:29
**/
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);
}
🍎🍎创建扩展了该记录器类的实体类🍎🍎
/**
* 创建扩展了该记录器类的实体类
* @description: InfoLogger
* @author: 庄霸.liziye
* @create: 2022-04-16 07:38
**/
class InfoLogger extends AbstractLogger {
public InfoLogger(int level){
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Info Logger:" + message);
}
}
class DeBugLogger extends AbstractLogger {
public DeBugLogger(int level){
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("DeBug Logger:" + message);
}
}
class ErrorLogger extends AbstractLogger {
public ErrorLogger(int level){
this.level = level;
}
@Override
protected void write(String message) {
System.out.println("Error Logger:" + message);
}
}
🍎🍎创建不同类型的记录器🍎🍎
/**
* @description: Test
* @author: 庄霸.liziye
* @create: 2022-04-16 07:51
**/
public class Test {
private static AbstractLogger getChainOfLoggers(){
AbstractLogger infoLogger = new InfoLogger(AbstractLogger.INFO);
AbstractLogger deBugLogger = new DeBugLogger(AbstractLogger.DEBUG);
AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
infoLogger.setNextLogger(deBugLogger);
deBugLogger.setNextLogger(errorLogger);
return infoLogger;
}
public static void main(String[] args) {
AbstractLogger loggerChain = getChainOfLoggers();
loggerChain.logMessage(AbstractLogger.INFO, "这是普通日志信息");
loggerChain.logMessage(AbstractLogger.DEBUG,"这是调试日志信息");
loggerChain.logMessage(AbstractLogger.ERROR,"这是错误日志信息");
}
}
🍎🍎代码执行结果🍎🍎
🍓🍓责任链模式的优、缺点🍓🍓
最后我们总结一下责任链模式的优点与缺点👇
🍌🍌优点🍌🍌
🍋 优点一:降低耦合度。它将请求的发送者和接收者解耦。
🍋 优点二:简化了对象。使得对象不需要知道链的结构。
🍋 优点三:增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
🍋 优点四:增加新的请求处理类很方便。
🍋 优点五:实现了责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
🍌🍌缺点🍌🍌
🥝 缺点一:不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
🥝 缺点二:对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
🥝 缺点三:职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
🥝 缺点四:可能不容易观察运行时的特征,给排查错误增加了难度。
小结
本人经验有限,有些地方可能讲的没有特别到位,如果您在阅读的时候想到了什么问题,欢迎在评论区留言,我们后续再一一探讨🙇
希望各位小伙伴动动自己可爱的小手,来一波点赞+关注 (✿◡‿◡) 让更多小伙伴看到这篇文章~ 蟹蟹呦(●'◡'●)
如果文章中有错误,欢迎大家留言指正;若您有更好、更独到的理解,欢迎您在留言区留下您的宝贵想法。
爱你所爱 行你所行 听从你心 无问东西