自学内容网 自学内容网

设计模式讲解02—责任链模式(Chain)

1. 概述

定义责任链模式是一种行为型模式,在这个模式中,通常创建了一个接收者对象的链来处理请求,该请求沿着链的顺序传递。直到有对象处理该请求为止,从而达到解耦请求发送者和请求处理者的目的。

解释责任链模式通过将多个处理器(处理对象)以链式结构连接起来,使得请求沿着这条链传递,直到有一个处理器处理该请求为止。责任链模式允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

⭐什么是行为型模式?

答:行为型模式主要用于描述对类或对象怎样交互和怎样分配职责。行为型模式 (Behavioral Pattern) 是对 在不同的对象之间划分责任和算法的抽象化

2. 优缺点

优点:

  1. 降低耦合度:请求发送者和接收者都没有对方的明确信息,而是通过抽象处理器来链接。实现了请求的发送者和处理者之间的解耦。
  2. 灵活性:可以动态地增加或删除处理器,方便扩展和维护。
  3. 易于实现:在责任链模式中,每个具体的处理器只需要实现自己的功能即可,不需要知道整个请求链的存在,这样更加容易实现其功能。

缺点:

  1. 不能保证请求一定会被处理:在责任链模式中,由于请求的处理是由多个对象负责的,所以不能保证请求一定会被处理,存在由于漏洞导致请求无响应的风险。
  2. 性能问题:在应用责任链模式时需要控制链中的处理器数量,过多的处理器会导致处理时间增加,从而影响系统性能。
  3. 调试困难:责任链模式中的处理器是动态组合的,处理逻辑较为复杂,因此需要进行详细的测试和调试。

3. 使用场景

3.1. 应用实例

  1. 请假申请流程:公司内部的请假申请一般需要经过多级审批,每个审批者的职责不同,可以通过责任链模式实现申请者与处理者之间的解耦,让申请者的请求依次经过各个处理者的处理,直到最终得到审批结果。
  2. 商品退换货:在线商场中,如果用户需要对商品进行退换货,涉及到订单创建、退货申请、快递配送等诸多步骤,这些步骤可以通过责任链模式实现,让每个处理者负责自己的任务,将责任链串接起来,以便完成整个退换货流程。
  3. 请求处理中心:当一个请求需要经过多个处理节点进行处理时,可以采用责任链模式来组织这些处理节点,使得请求在节点之间循环传递,直到得到最终结果。例如,大型网站的访问请求处理中心,就可以采用责任链模式来处理请求。
  4. 系统安全中心:当系统发生安全威胁时,可以采用责任链模式来组织安全相关的处理节点,对异常数据进行检测和拦截,保障系统安全稳定运行。

3.2. 程序场景

  1. 请求的处理顺序不确定:如果一个系统中存在多个处理请求的对象,且请求的处理可能需要先后顺序,则可以采用责任链模式,让不同的处理对象构成责任链,依次对请求进行处理。
  2. 有多个对象可需要处理请求:如果一个请求可能需要由多个对象来进行处理,而这些处理对象之间相互独立,不需要知道其他处理对象的存在,则可以采用责任链模式来实现请求的处理。
  3. 需要动态安排处理流程:如果处理流程需要动态安排,可以通过动态组合责任链节点来实现。即根据实际需求,动态安排责任链的执行顺序和强度。
  4. 需要在不影响代码整体结构的情况下,进行功能扩展:使用责任链模式可以方便地扩展系统的功能,对业务逻辑和系统结构的初始设计基本无影响,只需要添加新的处理节点、修改处理节点间的联系即可。

4. 结构⭐

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

  • 抽象处理器(Handler)定义一个处理请求的接口,通常包含一个处理请求的方法(如 handleRequest)和一个指向下一个处理者的引用(后继者)。
  • 具体处理器(ConcreteHandler)实现了抽象处理器接口,负责处理请求。如果能够处理该请求,则直接处理;否则,将请求传递给下一个处理者。
  • 客户端(Client)创建处理者对象,并将它们连接成一条责任链。通常,客户端只需要将请求发送给责任链的第一个处理者,无需关心请求的具体处理过程。

5. 代码实现

5.1. 需求介绍

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

5.2. 代码演示

  1. 创建一个抽象的记录器类(抽象处理器)
/**
 * @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);
}

  1. 创建扩展了该记录器抽象类的具体实现类(具体抽象类)
/**
 * @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);
   }
}

  1. 创建不同类型的记录器,并赋予它们不同的错误级别,并在每个记录器中设置下一个记录器。(客户端)
/**
 * 客户端 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.

原文地址:https://blog.csdn.net/weixin_63944437/article/details/143566188

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!