如何在业务代码中优雅地使用责任链模式

简介: 责任链模式是一种行为设计模式,本文从责任链模式的定义到其优雅之处、合适的应用场景、应用示例、实现步骤等方面详细讲述了如何在业务代码中优雅的使用责任链模式。

一、引言

在软件开发中,我们经常会遇到一种情况,即一个请求需要经过多个处理节点才能得到最终结果。这种情况下,我们可以使用责任链模式来优雅地处理请求。责任链模式是一种行为设计模式,它可以创建一条由多个处理节点组成的链,每个节点都有机会处理请求,也可以决定将请求传递给下一个节点。这种模式可以将请求的发送者和接收者解耦,从而提高代码的灵活性和可维护性。


责任链模式的使用场景通常包括以下几种情况:


1.有多个对象可以处理请求,但具体由哪个对象处理请求在运行时才能确定。

2.想要在不明确指定接收者的情况下,向多个对象中的一个提交请求。

3.希望动态指定处理请求的对象集合。


二、责任链模式的定义


1. 定义

使多个对象都有机会处理请求,从而避免请求的发送者与请求处理者耦合在一起。将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。


2. 类型

对象行为型模式。


3. 实质

责任链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,从而实现请求发送者与请求处理者的解耦。


三、优雅之处


使用责任链模式的好处和目标主要有以下几点:


1.解耦责任链的节点:责任链模式可以将请求的发送者和接收者解耦,使得它们不需要直接相互引用,从而降低了对象之间的耦合度。


2.提高代码的灵活性和可维护性:责任链模式可以在运行时动态地改变处理节点的顺序和数量,从而灵活地处理不同的请求,同时也方便了代码的维护和扩展。


3.增加新的处理节点方便:由于责任链模式将处理节点解耦,因此可以方便地增加新的处理节点到责任链中,而不需要修改已有的代码。


4.动态处理请求:责任链模式允许在运行时根据具体的情况动态地组合和排序处理者,从而实现灵活的请求处理逻辑。


通过使用责任链模式,我们可以更加灵活和优雅地处理请求,降低代码之间的耦合度,提高代码的可维护性和可扩展性。在一些具有复杂业务逻辑或需要动态处理请求的场景下,使用责任链模式将是一个很好的选择。接下来,我们将通过一个具体的示例来详细介绍如何在业务代码中优雅地使用责任链模式。

四、责任链模式适合应用场景

当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时, 可以使用责任链模式。


该模式能将多个处理者连接成一条链。 接收到请求后, 它会 “询问” 每个处理者是否能够对其进行处理。 这样所有处理者都有机会来处理请求。


当必须按顺序执行多个处理者时, 可以使用该模式。


无论你以何种顺序将处理者连接成一条链, 所有请求都会严格按照顺序通过链上的处理者。


如果所需处理者及其顺序必须在运行时进行改变, 可以使用责任链模式。


如果在处理者类中有对引用成员变量的设定方法, 你将能动态地插入和移除处理者, 或者改变其顺序。


实现方式


1.声明处理者接口并描述请求处理方法的签名


确定客户端如何将请求数据传递给方法。 最灵活的方式是将请求转换为对象, 然后将其以参数的形式传递给处理函数。


2.为了在具体处理者中消除重复的样本代码 你可以根据处理者接口创建抽象处理者基类


该类需要有一个成员变量来存储指向链上下个处理者的引用。 你可以将其设置为不可变类。 但如果你打算在运行时对链进行改变, 则需要定义一个设定方法来修改引用成员变量的值。


为了使用方便, 你还可以实现处理方法的默认行为。 如果还有剩余对象, 该方法会将请求传递给下个对象。 具体处理者还能够通过调用父对象的方法来使用这一行为。


3.依次创建具体处理者子类并实现其处理方法 每个处理者在接收到请求后都必须做出两个决定


  • 是否自行处理这个请求
  • 是否将该请求沿着链进行传递


4.客户端可以自行组装链 或者从其他对象处获得预先组装好的链 在后一种情况下 你必须实现工厂类以根据配置或环境设置来创建链


5.客户端可以触发链中的任意处理者 而不仅仅是第一个 请求将通过链进行传递 直至某个处理者拒绝继续传递 或者请求到达链尾


6.由于链的动态性 客户端需要准备好处理以下情况


  • 链中可能只有单个链接
  • 部分请求可能无法到达链尾
  • 其他请求可能直到链尾都未被处理


五、应用示例


我们拿请假的场景来说明,我们请假时间分为3天,5天,7天等,对应请假天数审批人不同,可能请假3天由你的项目小组长审批即可,但是请假5天可能需要由部门总来审批。在这个场景中就十分适合使用责任链模式进行构建。当然也可以用大量的if-else来处理,但是相对于if-else来讲责任链模式由些好处:


1.责任链模式与if...else相比,他的耦合性要低一些,因为它将条件判定分散到各个处理类中,并且这些处理类的优先处理顺序可以随意的设定,并且如果想要添加新的handler类也是十分简单的,这符合开放闭合原则。


2.责任链模式带来了灵活性,但是在设置处理类前后关系时,一定要避免在链中出现循环引用的问题。

image.png

六、实现步骤


循环责任链模式步骤

使用for循环来处理责任链可以更加直观地解释责任链模式的执行过程。


假设我们有一个责任链,包含了多个处理器Processor1、Processor2、Processor3。每个处理器都可以处理请求,如果一个处理器能够处理请求,就处理并结束责任链的执行;如果处理器不能处理请求,就将请求传递给下一个处理器。


我们可以使用一个for循环来遍历责任链中的处理器,并依次进行处理。当遇到第一个能够处理请求的处理器时,就处理请求并结束循环。


Request request = new Request(); // 创建请求对象

Processor[] processors = {new Processor1(), new Processor2(), new Processor3()};

for (Processor processor : processors) {
    if (processor.canHandle(request)) {
        processor.process(request);
        break; // 处理请求并结束循环
    }
}

在上述代码中,我们依次遍历责任链中的处理器,通过调用canHandle方法判断是否能够处理请求。如果能够处理,则调用process方法进行处理,并使用break语句结束循环。如果所有处理器都不能处理请求,循环结束后可以进行相应的处理逻辑。


使用for循环来处理责任链能够更加清晰地表达责任链模式的执行过程,我们按照顺序遍历处理器,并根据需要进行处理。如果有多个处理器都能处理请求,我们可以通过调整处理器的顺序来确定处理的优先级。同时,我们也可以在循环结束后根据实际需求进行相应的处理,比如报错或给出默认处理等。

image.png

责任链模式的设计思想就是将一个请求沿着一条链传递,每个节点都有机会处理请求或者将其传递给下一个节点。这种设计类似于流水线上的工作流程,每个节点都负责处理某个环节的工作,并将结果传递给下一个节点。使用流程图可以很好地表示责任链模式的执行流程。每个节点可以表示为一个流程图中的步骤,箭头表示请求的传递方向。整个流程图可以清晰地展示责任链模式中各个节点的工作顺序和流程。


通过流程图的抽象表示,我们可以更好地理解责任链模式的执行流程,便于沟通和交流,也有助于设计和实现责任链模式。同时,流程图也可以帮助开发人员更好地理解和维护责任链模式的代码逻辑。


请假场景步骤

请假场景中的责任链模式可以通过实现一个LeaveRequestProcessor接口来实现,每个具体处理者都实现该接口,根据请假天数来确定是否能够处理请求,以及是否将请求传递给下一个处理者。


使用for循环来实现责任链模式可以更加直观地展示责任链的执行过程:


首先,定义LeaveRequestProcessor接口:

public interface LeaveRequestProcessor {
    void processLeaveRequest(LeaveRequest request);
}

1.TeamLeaderProcessor(项目小组长处理器):

public class TeamLeaderProcessor implements LeaveRequestProcessor {
    public void processLeaveRequest(LeaveRequest request) {
        if (request.getDays() <= 3) {
            // 处理请假请求
            System.out.println("项目小组长批准了请假申请,天数为:" + request.getDays() + "天");
        } else {
            System.out.println("项目小组长无法处理该请假申请");
        }
    }
}

2.DepartmentManagerProcessor(部门经理处理器):

public class DepartmentManagerProcessor implements LeaveRequestProcessor {
    public void processLeaveRequest(LeaveRequest request) {
        if (request.getDays() > 3 && request.getDays() <= 5) {
            // 处理请假请求
            System.out.println("部门经理批准了请假申请,天数为:" + request.getDays() + "天");
        } else {
            System.out.println("部门经理无法处理该请假申请");
        }
    }
}

3.CEOProcessor(总经理处理器):

public class CEOProcessor implements LeaveRequestProcessor {
    public void processLeaveRequest(LeaveRequest request) {
        if (request.getDays() > 5 && request.getDays() <= 7) {
            // 处理请假请求
            System.out.println("总经理批准了请假申请,天数为:" + request.getDays() + "天");
        } else {
            System.out.println("总经理无法处理该请假申请");
        }
    }
}

然后,创建一个处理器列表,并使用for循环遍历处理器列表来处理请假请求:

List<LeaveRequestProcessor> processors = new ArrayList<>();
processors.add(new TeamLeaderProcessor());
processors.add(new DepartmentManagerProcessor());
processors.add(new CEOProcessor());

// 创建请假请求
LeaveRequest request = new LeaveRequest("John", 5);

for (LeaveRequestProcessor processor : processors) {
    processor.processLeaveRequest(request);
}

在上述代码中,我们创建了一个处理器列表,并依次添加了项目小组长(Team Leader Processor)、部门经理(Department Manager Processor)和总经理(CEO Processor)这三个具体处理者。然后,我们使用for循环遍历处理器列表,并依次调用每个处理器的process Leave Request方法来处理请假请求。


每个处理器在处理请求时,根据请假天数来判断是否能够处理请求。如果能够处理请求,则进行处理并结束循环;如果不能处理请求,则继续下一个处理器。这样,请求会依次在处理器列表中传递,直到找到能够处理请求的处理器为止。


通过使用for循环来实现责任链模式,我们更加直观地表达了责任链模式的执行过程。同时,通过调整处理器在处理器列表中的顺序,可以灵活地改变处理请求的优先级。在业务逻辑发生变化时,我们只需要新增或修改相应的处理器即可,而不需要修改已有的处理器或请求发送者的代码,提高了代码的可维护性和可扩展性。


这样,通过责任链模式,我们可以灵活地处理请假请求,并且根据请假天数确定由哪个处理者来审批。在业务逻辑发生变化时,我们只需要新增或修改相应的处理者即可,而不需要改动已有的处理者或请求发送者的代码,提高了代码的可维护性和可扩展性。


参考资料:

责任链的使用:https://juejin.cn/post/7273028474981335081 

责任链模式:https://refactoringguru.cn/design-patterns/chain-of-responsibility 




来源  |  阿里云开发者公众号
作者  |  问空





















































































相关文章
|
9天前
|
设计模式 数据安全/隐私保护
探索责任链模式:在项目中的应用与实践
在软件设计模式中,责任链模式(Chain of Responsibility)是一种对象行为型模式,它允许一个请求沿着链式结构的多个对象传递,直到有一个对象处理它为止。这种模式在实际项目中有着广泛的应用,尤其是在处理复杂的业务逻辑和解耦系统中。本文将分享责任链模式的基本概念、应用场景以及在项目中的实践案例。
32 5
|
4月前
|
前端开发 JavaScript 开发者
条件判断的模式问题之为什么不建议在前端日常业务开发中使用OOP的责任链模式实践
条件判断的模式问题之为什么不建议在前端日常业务开发中使用OOP的责任链模式实践
|
5月前
|
设计模式 监控 开发者
在业务代码中如何优雅地使用责任链模式
在日常开发中,随着业务逻辑的复杂性和系统规模的增加,我们开发者往往面临着代码结构混乱、模块间耦合度高等问题,如何保持代码的清晰、可维护和可扩展性成为了一个重要的挑战。为了解决这个问题,我们需要借助一些设计模式来优化代码结构,提高代码的可读性和可维护性,那么责任链模式就是一种非常实用的设计模式,是解决这一问题的有效手段之一,它可以帮助我们优雅地处理业务逻辑中的复杂请求,该模式通过构建一系列处理者对象,并将它们连接成一条链,使得请求可以在这些处理者之间传递,直到被恰当处理。那么接下来,我们将探讨如何在业务代码中优雅地使用责任链模式,欢迎在评论区留言交流。
74 5
在业务代码中如何优雅地使用责任链模式
|
4月前
|
设计模式 算法
交易链路设计原则&模式问题之中介者(Mediator)方法设计模式是什么,如何解决
交易链路设计原则&模式问题之中介者(Mediator)方法设计模式是什么,如何解决
|
6月前
|
设计模式 缓存 Java
如何在业务代码中优雅地使用责任链模式?
【5月更文挑战第26天】责任链模式(Chain of Responsibility Pattern)是一种设计模式,用于处理请求的发送者和接收者之间的解耦。
110 1
|
6月前
|
Java
如何在业务代码中优雅地使用责任链模式
如何在业务代码中优雅地使用责任链模式
|
6月前
|
设计模式 关系型数据库 Java
顺畅的职责传递-用责任链模式优化决策流程
本文首先通过经典场景展示了不使用设计模式时的问题与痛点。接着,引入责任链模式,详细讲解了其定义、解决问题的方式、结构图及工作原理,并通过重构示例展示了该模式如何解决原有痛点。最后,对责任链模式的优势、缺点以及在实际应用中可能遇到的挑战和限制进行了总结。责任链模式通过解耦请求发送者和接收者,提供了灵活的请求处理机制,适用于多个处理者按顺序处理请求的场景。然而,该模式也可能导致请求得不到处理或性能下降等问题,需在实际应用中权衡利弊。
232 0
顺畅的职责传递-用责任链模式优化决策流程
|
6月前
|
设计模式
二十三种设计模式全面解析-职责链模式(Chain of Responsibility Pattern):解放代码责任链,提升灵活性与可维护性
二十三种设计模式全面解析-职责链模式(Chain of Responsibility Pattern):解放代码责任链,提升灵活性与可维护性
|
设计模式 数据安全/隐私保护
这才是责任链模式的优雅使用方式
首先创建一个实体类Member。
107 0
|
设计模式 Java 测试技术
设计模式:使用状态模式推动业务全生命周期的流转
本文借助海外互金业务的借款流程展开讨论,随着业务状态不断增多,if-else分支代码充斥项目,如何通过状态模式去解耦业务中的状态的流转,通过合理的抽象满足面向对象设计的开闭原则,让业务优雅地扩展。
11759 0
设计模式:使用状态模式推动业务全生命周期的流转