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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 责任链模式是一种行为设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理它。每个处理者都有一个对下一个处理者的引用。责任链模式常用于处理请求的场景,例如在一个请求需要经过多个步骤或者多个对象来处理的情况下。

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日志并进行多维度分析。
目录
相关文章
|
5天前
|
设计模式 缓存 监控
【设计模式系列笔记】代理模式
代理模式是一种结构型设计模式,它允许一个对象(代理对象)控制另一个对象的访问。代理对象通常充当客户端和实际对象之间的中介,用于对实际对象的访问进行控制、监控或其他目的。
42 1
|
5天前
|
设计模式
【设计模式】张一鸣笔记:责任链接模式怎么用?
【设计模式】张一鸣笔记:责任链接模式怎么用?
11 1
|
5天前
|
设计模式 算法 Java
【设计模式系列笔记】设计模式与设计原则
设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。 设计原则是一些通用的设计指导方针,它们提供了如何设计一个优秀的软件系统的基本思想和规则。指导着设计者如何组织代码以实现高内聚、低耦合、易扩展和易维护的软件系统。
26 4
|
5天前
|
设计模式 JavaScript 前端开发
vue的设计模式_笔记
vue的设计模式_笔记
16 0
|
5天前
|
设计模式 算法 编译器
【设计模式系列笔记】访问者模式
访问者模式是一种行为设计模式,旨在将算法与对象结构分离,使得能够在不修改元素类的前提下定义新的操作。这一模式的核心思想是在元素类中添加一个接受访问者的方法,从而实现在不同元素上执行不同操作的能力。
33 0
|
5天前
|
设计模式 SQL 算法
【设计模式系列笔记】模板方法模式
模板方法模式是一种行为设计模式,它定义了一个算法的骨架,并允许子类在不改变该算法结构的情况下重新定义算法的某些步骤。这种模式属于行为型模式,它通过将算法的不同部分封装在不同的方法中,从而使子类能够在不改变算法结构的前提下定制算法的某些步骤。
32 0
|
5天前
|
设计模式 算法 Java
【设计模式系列笔记】策略模式
策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列的算法,将每个算法封装起来,并且使它们可以互相替换。策略模式使得算法可以独立于客户端而变化。
26 0
|
5天前
|
设计模式 Java
【设计模式系列笔记】状态模式
在Java中,状态模式是一种行为设计模式,它允许对象在其内部状态改变时改变其行为。状态模式的关键思想是将对象的状态封装成独立的类,并将对象的行为委托给当前状态的对象。这样,当对象的状态发生变化时,其行为也会相应地发生变化。
25 0
|
5天前
|
设计模式 消息中间件 存储
【设计模式系列笔记】观察者模式
观察者模式是一种设计模式,它允许一个对象(主题)维护一组依赖于它的对象(观察者)并在状态发生变化时通知它们。这种模式属于行为型模式。在观察者模式中,主题是被观察的对象,而观察者是依赖于主题的对象,当主题的状态发生变化时,所有注册的观察者都会得到通知并自动更新。
24 0
|
5天前
|
设计模式 存储
【设计模式系列笔记】备忘录模式
备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不暴露对象实现细节的情况下捕获并恢复其内部状态。这种模式属于行为型设计模式。备忘录模式通常包含以下几个角色:发起人,备忘录,管理者。
22 0