1. 概述
定义 : 责任链模式是一种行为型模式,在这个模式中,通常创建了一个接收者对象的链来处理请求,该请求沿着链的顺序传递。直到有对象处理该请求为止,从而达到解耦请求发送者和请求处理者的目的。
解释 **:**责任链模式通过将多个处理器(处理对象)以链式结构连接起来,使得请求沿着这条链传递,直到有一个处理器处理该请求为止。责任链模式允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
⭐什么是行为型模式?
答:行为型模式主要用于描述对类或对象怎样交互和怎样分配职责。行为型模式 (Behavioral Pattern) 是对 在不 同的对象之间划分责任和算法的抽象化 。
2. 优缺点
优点:
- 降低耦合度:请求发送者和接收者都没有对方的明确信息,而是通过抽象处理器来链接。实现了请求的发送者和处理者之间的解耦。
- 灵活性:可以动态地增加或删除处理器,方便扩展和维护。
- 易于实现:在责任链模式中,每个具体的处理器只需要实现自己的功能即可,不需要知道整个请求链的存在,这样更加容易实现其功能。
缺点:
- 不能保证请求一定会被处理:在责任链模式中,由于请求的处理是由多个对象负责的,所以不能保证请求一定会被处理,存在由于漏洞导致请求无响应的风险。
- 性能问题:在应用责任链模式时需要控制链中的处理器数量,过多的处理器会导致处理时间增加,从而影响系统性能。
- 调试困难:责任链模式中的处理器是动态组合的,处理逻辑较为复杂,因此需要进行详细的测试和调试。
3. 使用场景
3.1. 应用实例
- 请假申请流程:公司内部的请假申请一般需要经过多级审批,每个审批者的职责不同,可以通过责任链模式实现申请者与处理者之间的解耦,让申请者的请求依次经过各个处理者的处理,直到最终得到审批结果。
- 商品退换货:在线商场中,如果用户需要对商品进行退换货,涉及到订单创建、退货申请、快递配送等诸多步骤,这些步骤可以通过责任链模式实现,让每个处理者负责自己的任务,将责任链串接起来,以便完成整个退换货流程。
- 请求处理中心:当一个请求需要经过多个处理节点进行处理时,可以采用责任链模式来组织这些处理节点,使得请求在节点之间循环传递,直到得到最终结果。例如,大型网站的访问请求处理中心,就可以采用责任链模式来处理请求。
- 系统安全中心:当系统发生安全威胁时,可以采用责任链模式来组织安全相关的处理节点,对异常数据进行检测和拦截,保障系统安全稳定运行。
3.2. 程序场景
- 请求的处理顺序不确定:如果一个系统中存在多个处理请求的对象,且请求的处理可能需要先后顺序,则可以采用责任链模式,让不同的处理对象构成责任链,依次对请求进行处理。
- 有多个对象可需要处理请求:如果一个请求可能需要由多个对象来进行处理,而这些处理对象之间相互独立,不需要知道其他处理对象的存在,则可以采用责任链模式来实现请求的处理。
- 需要动态安排处理流程:如果处理流程需要动态安排,可以通过动态组合责任链节点来实现。即根据实际需求,动态安排责任链的执行顺序和强度。
- 需要在不影响代码整体结构的情况下,进行功能扩展:使用责任链模式可以方便地扩展系统的功能,对业务逻辑和系统结构的初始设计基本无影响,只需要添加新的处理节点、修改处理节点间的联系即可。
4. 结构⭐
责任链模式包含以下几个主要角色:
- 抽象处理器(Handler) : 定义一个处理请求的接口,通常包含一个处理请求的方法(如
handleRequest
)和一个指向下一个处理者的引用(后继者)。 - 具体处理器(ConcreteHandler) **:**实现了抽象处理器接口,负责处理请求。如果能够处理该请求,则直接处理;否则,将请求传递给下一个处理者。
- 客户端(Client) **:**创建处理者对象,并将它们连接成一条责任链。通常,客户端只需要将请求发送给责任链的第一个处理者,无需关心请求的具体处理过程。
5. 代码实现
5.1. 需求介绍
我们创建抽象类 AbstractLogger,带有详细的日志记录级别。然后我们创建三种类型的记录器,都扩展了 AbstractLogger。每个记录器判断消息的级别是否属于自己的级别,如果是则相应地打印出来,否则不打印并把消息传给下一个记录器。
5.2. 代码演示
-
创建一个抽象的记录器类(抽象处理器)
/**
-
@Description 记录器类 ------ 抽象处理器
-
@Author gongming.Zhang
-
@Date 2024/11/6 10:39
-
@Version 1.0
*/
public abstract class AbstractLogger {
public static final Integer INFO = 1;
public static final Integer DEBUG = 2;
public static final Integer ERROR = 3;// protected:对本包以及不同包的子类可见
protected Integer 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); }
}
// 抽象方法,具体的处理器去实现对应的逻辑
protected abstract void write(String message);
}
-
-
创建扩展了该记录器抽象类的具体实现类(具体抽象类)
/**
-
@Description 控制台日志类
-
@Author gongming.Zhang
-
@Date 2024/11/6 10:55
-
@Version 1.0
*/
public class ConsoleLogger extends AbstractLogger {public ConsoleLogger(int level) {
this.level = level;
}@Override
protected void write(String message) {
System.out.println("Standard Console::Logger: " + message);
}
}
/**
-
@Description 报错日志类
-
@Author gongming.Zhang
-
@Date 2024/11/6 10:58
-
@Version 1.0
*/
public class ErrorLogger extends AbstractLogger {public ErrorLogger(int level){
this.level = level;
}@Override
protected void write(String message) {
System.out.println("Error Console::Logger: " + message);
}
}
/**
-
@Description 文件日志类
-
@Author gongming.Zhang
-
@Date 2024/11/6 10:58
-
@Version 1.0
*/
public class FileLogger extends AbstractLogger {public FileLogger(int level){
this.level = level;
}@Override
protected void write(String message) {
System.out.println("File::Logger: " + message);
}
}
-
-
创建不同类型的记录器,并赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。(客户端)
/**
-
客户端 Client
-
@return 返回链头
*/
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;
}
/**
-
测试
*/
@Test
void testChainDesignPatterns() {
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.");
}
-
结果:
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.