设计模式学习之——责任链模式

devtools/2024/11/29 17:00:41/

责任链模式的基本概念

定义责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象按照一定顺序处理请求,并且每个对象可以选择自己是否处理该请求或者将其传递给下一个对象处理。

核心思想:将多个处理请求的对象组成一条链,请求在这条链上传递,直到有一个对象处理它。

主要角色

  • 抽象处理者(Handler):定义一个处理请求的接口,并持有对下一个处理者的引用;
  • 具体处理者(ConcreteHandler):实现抽象处理者的接口,处理请求或将请求传给下一个处理者;
  • 客户端(Client):发起请求的对象,不需要知道谁处理了请求,也不需要知道具体的处理者。

责任链模式的使用场景

责任链模式适用场景:

1、当有多个对象可以处理同一个请求时;

2、当处理者之间的顺序不确定时,可以动态组织处理者之前顺序;

3、当请求的处理流程需要灵活配置时;

责任链模式的优缺点

优点

1、降低了请求的发送者和接收者之前的耦合度;

2、提高了系统的灵活性和可扩展性,可以动态地增加或删除处理者;

3、使得请求的处理流程更加清晰和易于维护

缺点

1、可能会导致性能问题,特别是当责任链过长或请求在链中被频繁传递时;

2、如果责任链配置不当,可能会导致请求无法被正确处理;

3、调试时可能会比较复杂,因为请求在链中的传递过程可能涉及多个处理者;

代码示例

以下是一个使用Java语言实现责任链模式的示例,演示了如何处理不同类型的请求

// 抽象处理者接口
abstract class Handler {protected Handler nextHandler;public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public abstract void handleRequest(String request);
}// 具体处理者A
class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if ("A".equals(request)) {System.out.println("ConcreteHandlerA 处理请求: " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}// 具体处理者B
class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(String request) {if ("B".equals(request)) {System.out.println("ConcreteHandlerB 处理请求: " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}// 具体处理者C
class ConcreteHandlerC extends Handler {@Overridepublic void handleRequest(String request) {if ("C".equals(request)) {System.out.println("ConcreteHandlerC 处理请求: " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}// 客户端代码
public class Main {public static void main(String[] args) {// 创建处理器链Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();Handler handlerC = new ConcreteHandlerC();// 将处理器连接在一起handlerA.setNextHandler(handlerB);handlerB.setNextHandler(handlerC);// 发送请求handlerA.handleRequest("A"); // ConcreteHandlerA 处理请求: AhandlerA.handleRequest("B"); // ConcreteHandlerB 处理请求: BhandlerA.handleRequest("C"); // ConcreteHandlerC 处理请求: ChandlerA.handleRequest("D"); // 无处理者处理请求: D(请求被忽略)}
}

在上面的示例中,我们定义了三个具体处理者(ConcreteHandlerAConcreteHandlerB 和 ConcreteHandlerC),它们分别处理不同类型的请求("A"、"B" 和 "C")。客户端代码创建了一个处理器链,并将请求发送到链上的第一个处理者(handlerA)。根据请求的类型,相应的处理者会处理请求,或者将请求传递给下一个处理者。如果请求的类型不匹配任何处理者,则请求会被忽略。

其他:

责任链模式常见的一些实际应用场景:

  • 用户登录验证
    • 在这种场景下,不同的验证步骤可以看作责任链中的不同节点,依次进行验证,直到所有验证都通过或某个验证失败为止。
    • 手机验证码登录:需要进行用户是否存在、验证码是否为空、验证码是否正确、用户是否锁定、用户是否被禁用等校验。
    • 用户名密码登录:需要进行用户是否存在、用户是否被锁定、密码校验等校验。
  • 请求处理系统

    • 如Web应用中的过滤器链,每个过滤器负责处理不同类型的请求或执行不同的任务,如身份验证、日志记录、请求参数修改等。
    • 请求依次经过责任链中的各个处理器,直到被某个处理器处理或所有处理器都遍历完。
  • 日志系统

    • 不同的日志级别(如INFO、DEBUG、ERROR)会对应不同的处理器。
    • 每个处理器负责处理对应级别的日志消息,并将其记录到相应的日志文件中或发送到日志服务器。
  • 事件处理系统

    • 在图形用户界面(GUI)应用中,事件(如鼠标点击、键盘输入)会触发一系列的处理动作。
    • 这些处理动作可以看作责任链中的不同节点,依次进行处理,直到事件被完全处理或某个节点决定不再继续处理。
  • 数据校验和转换

    • 在数据接收或发送过程中,可能需要对数据进行一系列的校验和转换操作。
    • 这些操作可以看作责任链中的不同节点,依次对数据进行处理,直到数据满足要求或处理完成。
  • 金融业务审批流程

    • 如贷款审批、订单审批等,通常需要经过多个审批环节,每个环节都有相应的审批条件和审批人员。
    • 这些审批环节可以看作责任链中的不同节点,依次进行审批,直到审批通过或拒绝。
  • 消息过滤系统

    • 在消息传递系统中,可能需要对消息进行一系列的过滤操作,如过滤垃圾邮件、过滤敏感词汇等。
    • 这些过滤操作可以看作责任链中的不同节点,依次对消息进行过滤,直到消息满足要求或所有过滤器都遍历完。

责任链模式在这些场景中的应用,使得系统的处理流程更加灵活和可扩展。通过动态地添加或删除处理节点,可以轻松地调整系统的处理逻辑,而无需修改现有的代码结构。同时,责任链模式也使得请求的处理过程更加清晰和易于维护。

责任链模式或者设计模式使用的场景有很多,但是,是否适合使用也很关键,不要为了使用而使用,否则也可能会带来更多的bug~~~


http://www.ppmy.cn/devtools/137972.html

相关文章

Spring数据接收揭秘

RequestMapping RequestMapping是Spring框架中用于将HTTP请求映射到控制器的处理方法上的注解,它能将特定的HTTP请求与控制器中的方法进行关联,使开发者可以根据请求的路径、请求方法、请求头、请求参数等条件,来确定由哪个方法处理该请求&a…

利用Vue 3实现鼠标跟随效果案例

在Web开发领域,鼠标跟随效果是一种能显著提升页面交互性、增加动态感与趣味性的常见方式。接下来,我们将通过一个详细的案例,深入讲解如何运用Vue 3来打造一个更为完善的鼠标跟随效果组件,重点在于优化鼠标移动逻辑部分。 一、案…

如何在CodeIgniter中加载视图

在CodeIgniter中加载视图(view)是开发Web应用程序中的一个基本步骤。CodeIgniter的视图机制允许你将HTML与PHP代码分离,从而提高代码的可维护性和可读性。以下是如何在CodeIgniter中加载视图的基本步骤: 1. 创建一个控制器 首先…

python自幂数(包括水仙花数)

1、自幂数的定义 自幂数是指一个 n 位数,它的每个位上的数字的 n 次幂之和等于它本身。 n为1时,自幂数称为独身数。显然,0,1,2,3,4,5,6,7,8,9都是自幂数; n为2时,没有自幂数; n为3时,自幂数称为水仙花数,有…

Flutter:GetBuilder页面模板,可复用,视图,控制器分离

GetBuilder页面模板&#xff0c;之后都会在此基础上写页面。 view import package:flutter/material.dart; import package:get/get.dart;import index.dart;class GoodsListPage extends GetView<GoodsListController> {const GoodsListPage({super.key});// 主视图Widg…

计算机网络----基本概念

基本概念 在这一章从整体上介绍计算机网络的概况, 为后续的学习搭建起整体的框架; 介绍计算机网络中的基础术语和概念; 什么是因特网 『 因特网 』是一个世界范围内互联了数以亿计的计算设备的计算机网络; 因特网具体构成 因特网互联了数以亿计的计算设备, 这些设备被称为…

数字IC后端实现之PR工具中如何避免出现一倍filler的缝隙?

在数字IC后端实现中&#xff0c;由于有的工艺foundary不提供Filler1&#xff0c;所以PR工具Innovus和ICC2在做标准单元摆放时需要避免出现两个标准单元之间的缝隙间距是Filler1。为了实现这个目的&#xff0c;我们需要给PR工具施加一些特殊的placement constraint&#xff08;典…

使用GitZip for github插件下载git仓库中的单个文件

背景&#xff1a;git仓库不知道抽什么疯&#xff0c;下载不了单个文件&#xff0c;点击下载没有反应&#xff0c;遂找寻其他方法&#xff0c;在这里简单记录下。 使用GitZip for github插件下载仓库中的单个文件 1、首先在浏览器安装插件&#xff0c;并确保为打开状态。 2、然…