【设计模式系列笔记】责任链模式

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
简介: 责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理它。每个处理者都有一个对下一个处理者的引用。责任链模式常用于处理请求的场景,例如在一个请求需要经过多个步骤或者多个对象来处理的情况下。

1. 责任链模式介绍

责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理它。每个处理者都有一个对下一个处理者的引用。责任链模式常用于处理请求的场景,例如在一个请求需要经过多个步骤或者多个对象来处理的情况下。

在Java中,责任链模式的实现通常涉及一个抽象处理者(Handler)和具体处理者(ConcreteHandler)。每个具体处理者都有一个对下一个处理者的引用,以及处理请求的方法。请求首先传递给第一个处理者,如果它无法处理,则传递给下一个处理者,依此类推,直到找到一个能够处理请求的处理者。

2. 关键思想

责任链模式的关键思想是将请求的发送者和接收者解耦,并允许多个对象都有机会处理这个请求。责任链模式通过构建一个处理者链来实现这一目标,每个处理者都有责任判断自己能否处理请求,以及是否将请求传递给下一个处理者。

以下是责任链模式的关键思想:

  1. 处理者抽象类或接口(Handler): 定义一个处理请求的接口,通常包含一个处理请求的方法。处理者可能有一个对下一个处理者的引用。
  2. 具体处理者类(ConcreteHandler): 实现处理请求的具体逻辑。如果能够处理请求,则进行处理;否则,将请求传递给下一个处理者。
  3. 客户端(Client): 创建处理者链,并将请求发送给第一个处理者。

通过这种方式,请求会被沿着责任链传递,直到找到能够处理它的处理者。责任链模式使得请求的发送者和接收者之间解耦,可以动态地调整和扩展处理者链。每个处理者只需要关注自己能否处理请求,而不用担心整个处理流程的细节。

3、实现方式:

示例代码

/**
 * 抽象处理者类,定义了处理请求的接口和对下一个处理者的引用。
 */
public abstract class Handler {
    /**
     * 下一个处理者
     */
    protected Handler nextHandler;
    /**
     * 设置下一个处理者
     *
     * @param nextHandler 下一个处理者
     */
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }
    /**
     * 处理请求的抽象方法,具体处理逻辑由子类实现。
     *
     * @param request 请求内容
     */
    public abstract void handleRequest(String request);
}
/**
 * 具体处理者类,实现了处理请求的具体逻辑。
 */
public class ConcreteHandler1 extends Handler {
    /**
     * 处理请求的具体逻辑
     *
     * @param request 请求内容
     */
    @Override
    public void handleRequest(String request) {
        // 判断是否能够处理请求
        if (request.equals("A")) {
            System.out.println("ConcreteHandler1处理请求A");
        } else if (nextHandler != null) {
            // 不能处理则传递给下一个处理者
            nextHandler.handleRequest(request);
        }
    }
}
/**
 * 具体处理者类,实现了处理请求的具体逻辑。
 */
public class ConcreteHandler2 extends Handler {
    /**
     * 处理请求的具体逻辑
     *
     * @param request 请求内容
     */
    @Override
    public void handleRequest(String request) {
        // 判断是否能够处理请求
        if (request.equals("B")) {
            System.out.println("ConcreteHandler2处理请求B");
        } else if (nextHandler != null) {
            // 不能处理则传递给下一个处理者
            nextHandler.handleRequest(request);
        }
    }
}
/**
 * 客户端代码,创建处理者链并触发请求。
 */
public class Client {
    public static void main(String[] args) {
        // 创建具体处理者实例
        Handler handler1 = new ConcreteHandler1();
        Handler handler2 = new ConcreteHandler2();
        // 设置处理者链
        handler1.setNextHandler(handler2);
        // 触发请求
        handler1.handleRequest("A"); // 输出:ConcreteHandler1处理请求A
        handler1.handleRequest("B"); // 输出:ConcreteHandler2处理请求B
        handler1.handleRequest("C"); // 未找到处理者,无输出
    }
}

通过这种方式,请求会在处理者链上传递,直到找到能够处理它的处理者。客户端可以灵活地调整和配置处理者链,以满足不同的需求。

需要注意的是,责任链模式也可以通过递归来实现,即在处理者的handleRequest方法中调用自身。递归方式能够更灵活地处理不同情况,但需要注意控制递归的终止条件,以避免无限循环。

要点:

  1. 处理者链的构建: 构建责任链时,确定每个具体处理者的责任和处理逻辑,并通过设置setNextHandler方法将它们连接在一起形成链条。
  2. 责任判断: 在具体处理者的handleRequest方法中,需要进行责任的判断,即判断是否能够处理当前请求。如果能够处理,则执行相应逻辑;如果不能处理,则将请求传递给下一个处理者。
  3. 动态调整链条: 责任链模式允许在运行时动态地添加、删除或修改处理者,以满足不同的业务需求。
  4. 遍历整个链: 责任链模式通常要求请求被依次传递给整个链上的处理者,因此需要确保每个处理者都有机会处理请求。

注意事项:

  1. 链的深度: 过长或者过深的责任链可能会影响性能,因此在设计时需要权衡链的深度和性能。
  2. 请求丢失: 如果责任链没有被正确设置,可能会导致请求被丢失而无法被任何处理者处理。确保责任链的正确连接和处理。
  3. 循环引用: 避免在责任链中出现循环引用,这可能导致无限循环的处理,影响系统的正常运行。
  4. 每个处理者的职责: 确保每个具体处理者的职责是清晰的,不要将责任链变得过于复杂,使得代码难以维护和理解。
  5. 性能考虑: 在设计责任链时要考虑性能,确保链中的处理者数量不会对系统性能产生负面影响。
  6. 默认处理者: 可以为责任链设置一个默认处理者,用于处理无法被其他处理者处理的情况,避免请求无处可去。

责任链模式在一些场景下能够有效地简化代码结构,使得代码更具灵活性和可维护性。然而,在使用时需要谨慎考虑上述要点和注意事项,以确保责任链模式能够正确而高效地发挥作用。

优点:

  1. 松散耦合: 责任链模式将请求的发送者和接收者解耦,使得系统更加灵活,每个处理者只关心自己的处理逻辑,不需要知道整个处理流程。
  2. 动态链: 可以动态地改变或扩展责任链,新增或删除处理者,而不影响其他部分代码的修改,提高了系统的可扩展性。
  3. 单一职责原则: 每个具体处理者只负责处理自己的职责,符合单一职责原则,使得代码更加清晰、简洁。
  4. 可配置性: 客户端可以灵活地配置处理者链,根据实际需求进行定制,更容易适应不同的业务场景。

缺点:

  1. 请求的不确定性: 由于责任链模式中请求的处理者不确定,可能会导致某个请求无法被处理,或者一个请求被多个处理者处理。
  2. 性能问题: 在责任链较长的情况下,请求可能需要遍历整个链,性能可能受到一定影响。需要权衡链的深度和性能。
  3. 调试困难: 在责任链中,如果某个请求没有得到处理,或者被错误地处理,可能需要逐个追踪调试整个链,相对比较困难。

应用场景:

  1. 请求的处理顺序不确定: 当系统中的请求需要按照一定的顺序被处理,但处理者的顺序可能不确定时,可以考虑使用责任链模式。
  2. 多级审批流程: 例如请假审批、报销审批等场景,不同级别的审批人构成一个责任链,依次进行审批。
  3. 事件传递: 在图形界面系统中,鼠标、键盘等事件的处理往往就是采用责任链模式的一种应用。
  4. 日志记录: 日志系统中,可以根据不同的日志级别将日志交由不同的处理者处理,形成一个责任链。
  5. 过滤器链: 在Web开发中,过滤器链通常采用责任链模式,每个过滤器负责处理某一方面的逻辑,然后将请求传递给下一个过滤器。
  6. 异常处理: 在程序中,可以通过责任链模式处理异常,每个处理者负责处理一种类型的异常,或者将异常传递给下一个处理者。

总体来说,责任链模式适用于请求的发送者和接收者之间的解耦,以及需要动态调整处理流程的情况。在合适的场景下,责任链模式可以提高系统的灵活性和可维护性。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
8天前
|
设计模式 Java API
Kotlin教程笔记(50) - 改良设计模式 - 工厂模式
Kotlin教程笔记(50) - 改良设计模式 - 工厂模式
|
8天前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
|
8天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
|
3天前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
3天前
|
设计模式 Java Kotlin
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
|
4天前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
14 3
|
3天前
|
设计模式 算法 Kotlin
Kotlin教程笔记(53) - 改良设计模式 - 策略模式
Kotlin教程笔记(53) - 改良设计模式 - 策略模式
17 2
|
4天前
|
设计模式 安全 Java
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
Kotlin教程笔记(51) - 改良设计模式 - 构建者模式
13 1
|
4天前
|
设计模式 Java API
Kotlin教程笔记(50) - 改良设计模式 - 工厂模式
Kotlin教程笔记(50) - 改良设计模式 - 工厂模式
11 1
|
15天前
|
设计模式 JavaScript Scala
Kotlin - 改良设计模式 - 责任链模式
Kotlin - 改良设计模式 - 责任链模式
51 9