设计模式-行为型模式:责任链模式

简介: 设计模式-行为型模式:责任链模式

1、简介

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许你将请求沿着处理者链进行传递,直到有一个处理者能够处理该请求。在责任链模式中,处理者通过组成一条链,形成一个处理者链,每个处理者都有机会处理请求,直到请求被处理完毕或者没有任何处理者能够处理该请求。

2、组成部分

责任链模式是由多个处理者对象组成的一个链式结构,它包括以下两个组成部分:

  1. 抽象处理者(Handler):定义了一个处理请求的方法,通常是一个抽象类或接口,具体的处理者实现该方法。抽象处理者还可以定义一个指向下一个处理者对象的引用,以形成责任链。
  2. 具体处理者(Concrete Handler):实现了抽象处理者中定义的处理请求的方法,如果能够处理请求,则处理请求,否则将请求传递给下一个处理者对象。

在责任链模式中,每个具体处理者对象都可以根据自己的判断逻辑,选择将请求处理掉,或者传递给下一个处理者对象,这样就形成了一条链式结构,每个请求都会从链的头部开始,一直传递到链的尾部,直到某个处理者对象处理了请求,或者所有的处理者对象都无法处理该请求。由于每个具体处理者对象都只需要处理自己关注的请求类型,所以责任链模式可以实现请求的动态处理,提高代码的灵活性和可扩展性。

3、优缺点

责任链模式是一种常用的设计模式,其主要优点和缺点如下:

优点:

  1. 降低耦合度:责任链模式可以将请求的发送者和接收者解耦,使得请求发送者不需要知道哪个接收者会处理请求。
  2. 灵活性:责任链模式可以动态地组合处理者对象,实现灵活的请求处理过程。
  3. 可扩展性:可以很方便地添加或删除处理者对象,实现责任链的动态调整。
  4. 可维护性:责任链模式可以将复杂的请求处理过程分解为多个简单的处理步骤,并将每个步骤封装在一个处理者对象中,便于维护和扩展。
  5. 提高系统性能:责任链模式可以避免将一个请求发送给所有的接收者,从而提高系统的处理性能。

缺点:

  1. 处理不了循环依赖的问题:如果责任链上的处理者对象之间存在循环依赖,就可能导致死循环或者无法正确处理请求。
  2. 可能导致请求得不到处理:如果责任链上的所有处理者对象都无法处理请求,就会导致请求得不到处理,从而浪费系统资源。
  3. 降低系统的稳定性:如果责任链上的某个处理者对象出现故障或者错误,就可能导致整个系统崩溃。

4、使用场景

责任链模式是一种行为型设计模式,通常在以下场景中使用:

  1. 处理请求的场景:如果有多个对象可以处理同一个请求,但是每个对象可以处理的请求类型不同,或者处理请求的顺序不同,那么可以使用责任链模式。例如,一个网络服务器接收到一个请求后,需要先检查请求是否合法,然后再对请求进行处理,最后将响应发送给客户端。这个过程可以分成多个处理步骤,并将每个步骤封装在一个处理者对象中。
  2. 请求的处理顺序不确定的场景:在某些情况下,请求的处理顺序可能不确定,或者需要在运行时动态地决定请求的处理顺序。此时,可以使用责任链模式。例如,一个采购系统需要根据采购请求的金额和种类来决定是否需要多个部门的审批,这些部门的审批顺序可能不同,可以将每个部门的审批封装在一个处理者对象中,然后根据采购请求的金额和种类,动态地组合这些处理者对象,构成一个处理者链。
  3. 需要动态添加或删除处理者的场景:在某些情况下,需要动态地添加或删除处理者对象,以便扩展处理者链或者优化请求处理过程。这时,可以使用责任链模式。例如,一个电商网站需要根据用户的购买记录、信用评分、账户余额等信息来决定是否给用户发放优惠券。这些信息可以由不同的处理者对象来获取,而这些处理者对象可以根据业务需求动态地添加或删除。
  4. 处理请求的对象不需要知道哪个对象处理该请求的场景:在某些情况下,处理请求的对象不需要知道最终哪个对象会处理该请求,而只需要将请求传递给责任链中的第一个处理者对象即可。例如,一个日志记录系统需要将日志分别记录到本地文件、远程服务器、数据库等不同的存储介质中,但是处理请求的对象只需要将日志记录到责任链中的第一个处理者对象中,就可以自动地将日志记录到多个存储介质中。

5、代码实现

在 Java 中实现责任链模式需要创建一个处理者接口或抽象类来定义处理请求的方法,并创建多个具体处理者类来实现该接口或抽象类。处理者对象通常需要维护一个指向下一个处理者的引用,以便将请求转发给下一个处理者。在客户端中,需要将多个处理者对象按照一定顺序组成一个责任链,然后将请求发送给责任链中的第一个处理者。

下面是一个简单的 Java 代码示例,演示如何使用责任链模式来处理采购请求:

首先,我们需要定义一个采购请求类,用于封装采购请求的信息:

1. public class PurchaseRequest {
2. private String item;    // 采购物品
3. private int amount;     // 采购金额
4. 
5. public PurchaseRequest(String item, int amount) {
6. this.item = item;
7. this.amount = amount;
8.     }
9. 
10. public String getItem() {
11. return item;
12.     }
13. 
14. public int getAmount() {
15. return amount;
16.     }
17. }

接下来,我们需要定义一个处理者接口,用于定义处理请求的方法,并定义一个抽象处理者类,实现该接口,并包含一个指向下一个处理者的引用:

1. public interface PurchaseHandler {
2. void handleRequest(PurchaseRequest request);
3. }
4. 
5. public abstract class AbstractPurchaseHandler implements PurchaseHandler {
6. protected PurchaseHandler nextHandler;
7. 
8. public void setNextHandler(PurchaseHandler nextHandler) {
9. this.nextHandler = nextHandler;
10.     }
11. }

然后,我们需要创建多个具体处理者类,继承抽象处理者类,实现处理请求的方法,并根据业务需求判断是否需要将请求转发给下一个处理者:

1. public class DepartmentHandler extends AbstractPurchaseHandler {
2. public void handleRequest(PurchaseRequest request) {
3. if (request.getAmount() < 1000) {
4.             System.out.println("DepartmentHandler approved the purchase of " + request.getItem());
5.         } else if (nextHandler != null) {
6.             nextHandler.handleRequest(request);
7.         } else {
8.             System.out.println("Sorry, your request for " + request.getItem() + " cannot be approved.");
9.         }
10.     }
11. }
12. 
13. public class ManagerHandler extends AbstractPurchaseHandler {
14. public void handleRequest(PurchaseRequest request) {
15. if (request.getAmount() < 5000) {
16.             System.out.println("ManagerHandler approved the purchase of " + request.getItem());
17.         } else if (nextHandler != null) {
18.             nextHandler.handleRequest(request);
19.         } else {
20.             System.out.println("Sorry, your request for " + request.getItem() + " cannot be approved.");
21.         }
22.     }
23. }
24. 
25. public class CEOHandler extends AbstractPurchaseHandler {
26. public void handleRequest(PurchaseRequest request) {
27. if (request.getAmount() < 10000) {
28.             System.out.println("CEOHandler approved the purchase of " + request.getItem());
29.         } else {
30.             System.out.println("Sorry, your request for " + request.getItem() + " cannot be approved.");
31.         }
32.     }
33. }

最后,在客户端中,我们需要将多个处理者对象按照一定顺序组成一个责任链,并将请求发送给责任链中的第一个处理者:

1. public class Client {
2. public static void main(String[] args) {
3. PurchaseRequest request1 = new PurchaseRequest("Pen", 800);
4. PurchaseRequest request2 = new PurchaseRequest("Phone", 5000);
5. PurchaseRequest request3 = new PurchaseRequest("Laptop", 15000);
6. 
7. DepartmentHandler departmentHandler = new DepartmentHandler();
8. ManagerHandler managerHandler = new ManagerHandler();
9. CEOHandler ceoHandler = new CEOHandler();
10. 
11.     departmentHandler.setNextHandler(managerHandler);
12.     managerHandler.setNextHandler(ceoHandler);
13. 
14.     departmentHandler.handleRequest(request1);
15.     departmentHandler.handleRequest(request2);
16.     departmentHandler.handleRequest(request3);
17.     }
18. }

在上面的客户端代码中,我们首先创建了三个采购请求对象,分别对应于购买笔、手机和笔记本电脑。然后,我们创建了三个具体处理者对象,即部门经理处理者、总经理处理者和CEO处理者。接着,我们将这三个处理者对象按照一定顺序组成一个责任链,即部门经理处理者处理不了的请求将转发给总经理处理者,总经理处理者处理不了的请求将转发给CEO处理者。最后,我们将三个采购请求对象发送给部门经理处理者,观察每个请求的处理结果。

运行上面的代码,我们可以得到如下输出:

       DepartmentHandler approved the purchase of Pen

       ManagerHandler approved the purchase of Phone

       CEOHandler approved the purchase of Laptop

从输出结果可以看出,当采购请求的金额小于 1000 时,部门经理处理者会批准请求;当采购请求的金额介于 1000 和 5000 之间时,总经理处理者会批准请求;当采购请求的金额介于 5000 和 10000 之间时,CEO处理者会批准请求;当采购请求的金额超过 10000 时,所有处理者都无法处理请求。这符合责任链模式的工作原理。

需要注意的是,在实际应用中,责任链模式中的每个处理者都应该具备一定的处理能力和处理权限,不能只是简单地转发请求。否则,责任链模式可能会失去效果,反而增加了系统的复杂性。

相关实践学习
通过日志服务实现云资源OSS的安全审计
本实验介绍如何通过日志服务实现云资源OSS的安全审计。
相关文章
|
4月前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
533 2
|
9月前
|
设计模式 网络协议 Java
【设计模式】【行为型模式】状态模式(State)
一、入门 什么是状态模式? 状态模式(State Pattern)是一种行为设计模式,允许对象在其内部状态改变时改变其行为,使其看起来像是改变了类。状态模式的核心思想是将对象的状态封装成独立的类,并将
369 16
|
9月前
|
设计模式 算法 前端开发
【设计模式】【行为型模式】职责链模式(Chain of Responsibility)
一、入门 什么是职责链模式? 职责链模式是一种行为设计模式,它允许你将请求沿着一条链传递,直到有对象处理它为止。每个对象都有机会处理请求,或者将其传递给链中的下一个对象。 为什么需要职责链模式? 使用
349 16
|
9月前
|
设计模式 存储 Java
【设计模式】【行为型模式】备忘录模式(Memento)
一、入门 什么是备忘录模式? 备忘录模式(Memento Pattern)是一种行为设计模式,用于在不破坏封装性的前提下,捕获并外部化一个对象的内部状态,以便在需要时恢复该状态。它通常用于实现撤销操作
305 8
|
5月前
|
设计模式 人工智能 算法
基于多设计模式的状态扭转设计:策略模式与责任链模式的实战应用
接下来,我会结合实战案例,聊聊如何用「策略模式 + 责任链模式」构建灵活可扩展的状态引擎,让抽奖系统的状态管理从「混乱战场」变成「有序流水线」。
|
9月前
|
设计模式 消息中间件 Java
【设计模式】【行为型模式】命令模式(Command)
一、入门 什么是命令模式? 命令模式是一种行为设计模式,它将请求或操作封装为对象,从而使你可以用不同的请求对客户进行参数化,并支持请求的排队、记录、撤销等操作。 命令模式的核心是将“请求”封装为独立的
275 15
|
9月前
|
设计模式 算法 搜索推荐
【设计模式】【行为型模式】策略模式(Strategy)
一、入门 什么是策略模式? 策略模式是一种行为设计模式,允许在运行时选择算法或行为。它将算法封装在独立的类中,使得它们可以互换,而不影响客户端代码。 为什么需要策略模式? 策略模式的主要目的是解决算法
199 14
|
9月前
|
设计模式 数据采集 算法
【设计模式】【行为型模式】模板方法模式(Template Method)
一、入门 1.1、什么是模板方法模式? 模板模式(Template Method Pattern)是一种行为设计模式,它定义了一个算法的框架,并允许子类在不改变算法结构的情况下重新定义算法的某些步骤。
295 13
|
9月前
|
设计模式 Java 编译器
【设计模式】【行为型模式】解释器模式(Interpreter)
一、入门 什么是解释器模式? 解释器模式(Interpreter Pattern)是一种行为设计模式,用于定义语言的语法表示,并提供一个解释器来处理该语法。它通常用于需要解释和执行特定语言或表达式的场
221 11
|
9月前
|
设计模式 存储 JavaScript
【设计模式】【行为型模式】迭代器模式(Iterator)
一、入门 什么是迭代器模式? 迭代器模式(Iterator Pattern)是一种行为设计模式,它提供了一种顺序访问聚合对象中元素的方法,而不需要暴露其底层表示。迭代器模式将遍历逻辑从聚合对象中分离出
252 11