当前位置: 首页 > news >正文

设计模式(四)——责任链模式

1. 责任链模式的定义

责任链模式(Chain of Responsibility,简称 CoR,也叫职责链模式)是一种行为型设计模式,允许一个请求在一系列处理器(handlers)中传递。每个处理器可以选择自己处理该请求,或者将其传递给下一个处理器。
一个大家比较熟悉的场景是找售后客服,通常是机器人客服先出来接待,然后在你的多次要求下转给人工客服,如果是设备维修可能还需要转到专业人员。这个场景就很适合应用责任链模式。总结一下就是这个模式适用于设计灵活、解耦的请求处理流水线。
在这里插入图片描述

2. 案例分析

2.1 需求

假设你被安排开发一个在线订购系统。在用户下单前,系统需要执行以下检查:

  • 验证用户身份(Authenticate)
  • 若有需要,校验管理员权限(Authorize)
  • 清理和预处理输入数据(Sanitize)
  • 阻止重复失败的请求(安全性)
  • 如果有缓存则直接返回缓存结果

2.2 潜在问题

如果把所有这些检查逻辑写在一个很长的方法里,你会发现:

  • 代码变得冗长混乱,难维护;
  • 添加或移除检查逻辑很麻烦;
  • 想在别处复用检查逻辑会产生大量重复代码。

2.3 基于责任链的解决方案

责任链模式将每个检查逻辑封装为独立的处理器类(handler),在其中定义 handle() 方法来解决上述问题。
每个处理器可以自行决定:

  • 是否处理当前请求;
  • 是否将请求传递给下一个处理器。
    最后将这些处理器串联起来,形成一个处理流水线(chain)
2.3.1 类定义
  • Handler(处理器接口)
  • BaseHandler(可选的抽象基类,提供链式调用逻辑)
  • AuthHandler(认证处理器)
  • SanitizeHandler(数据清理处理器)
  • CacheHandler(缓存处理器)
    每个处理器只需要知道下一个处理器,从而让请求顺序向下传递。
2.3.2 具体实现

步骤 1:定义处理器接口

interface Handler {void handle(Request request);
}

步骤 2:创建基础处理器 BaseHandler(可选)

// BaseHandler 提供了公共逻辑,用于链接和转发请求。
// 它实现了 Handler 接口。
abstract class BaseHandler implements Handler {// 保存下一个处理器的引用private Handler next;/*** 设置链中的下一个处理器。* 允许像这样链式调用:auth.setNext(validation).setNext(logger);** @param next 下一个处理器* @return 返回传入的处理器,用于链式调用*/public BaseHandler setNext(Handler next) {this.next = next;return (BaseHandler) next;}/*** 如果存在下一个处理器,则将请求转发给它。** @param request 需要传递的请求对象*/protected void forward(Request request) {if (next != null) {// 委托给下一个处理器next.handle(request);  }}
}

BaseHandler 是一个抽象类,不能直接使用,而是由具体的处理器(如 AuthHandlerValidationHandler 等)继承。
它封装了职责链的核心逻辑:

  • setNext() 设置下一个处理器并返回它,以便链式调用;
  • forward() 将请求传递给下一个处理器。

具体处理器类只需要关注自身的 handle() 逻辑,执行完后调用 forward(request) 即可。

步骤 3:定义请求对象

class Request {public String user;public boolean isAdmin;public boolean isValid = true;public boolean isCached;// ... 字段可以根据需要扩展
}

步骤 4:创建具体的处理器

// Handler 1: 检查用户是否已登录
class AuthHandler extends BaseHandler {@Overridepublic void handle(Request request) {if (request.user == null) {System.out.println("[Auth] 用户未认证,请求终止。");// 不再向下传递return; }System.out.println("[Auth] 用户已认证。");// 交给下一个处理器forward(request); }
}// Handler 2: 管理员权限校验
class AdminHandler extends BaseHandler {@Overridepublic void handle(Request request) {if (!request.isAdmin) {System.out.println("[Admin] 普通用户,跳过管理员校验。");} else {System.out.println("[Admin] 管理员验证通过。");// 可执行管理员相关逻辑}forward(request);}
}// Handler 3: 数据清理
class SanitizeHandler extends BaseHandler {@Overridepublic void handle(Request request) {System.out.println("[Sanitize] 正在清理数据...");forward(request);}
}

步骤 5:组装责任链

public class ChainApp {public static void main(String[] args) {Request request = new Request();request.user = "哈基米";request.isAdmin = true;Handler chain = new AuthHandler();chain.setNext(new AdminHandler()).setNext(new SanitizeHandler());chain.handle(request);}
}
2.3.3 执行流程
  1. AuthHandler 验证用户;
  2. 验证通过后,将请求传递给 AdminHandler
  3. 再传递到 SanitizeHandler
  4. 如果某个处理器中断了链条,后续处理器将不会执行。

3. 优缺点分析

3.1 优势

  • 处理器可复用,且易于单元测试;
  • 可以在运行时动态配置责任链;
  • 逻辑清晰,符合 单一职责原则(SRP)
  • 处理顺序不在处理器内部硬编码,而是通过链式结构灵活定义。

3.2 缺点

  • 如果链条覆盖不全,可能存在请求未被处理的情况;
  • 请求在长链路中传递时,跟踪路径可能较困难;
  • 动态链条的调试可能比较复杂,需要设计合适的日志记录方式。

4. 使用

4.1 常见应用场景

  • 中间件管道(认证、校验、日志记录)
  • GUI 事件处理(鼠标/键盘事件)
  • 垃圾邮件过滤
  • 文件格式识别

4.2 适用场景

当满足以下条件时,可以考虑使用职责链模式:

  • 有多个对象可以处理同一个请求;
  • 需要解耦请求发送方和接收方;
  • 需要复用或动态调整处理逻辑顺序;
  • 需要在某些条件下提前终止处理流程。

总结

**职责链模式的核心在于灵活性。**使得逻辑可以像流水线一样串联起来,每个处理器专注于一个小任务。合理的使用这种模式可以让代码逻辑更加清晰、便于测试和扩展,还能避免冗长的条件分支。

http://www.lryc.cn/news/624717.html

相关文章:

  • 福彩双色球第2025095期篮球号码分析
  • 19.8 《3步实现OPT-6.7B无损量化:用自定义数据集省70%显存,精度仅跌2.3%》
  • 终极方案!lightRag/graphRag离线使用tiktoken持续报错SSLError,不改源码,彻底解决!
  • 海洋牧场邂逅海洋旅游:碰撞出新业态的璀璨火花
  • 北斗安心联车辆管理系统优势分析
  • 飞机起落架轮轴深孔中间段电解扩孔内轮廓检测 - 激光频率梳 3D 轮廓检测
  • Conda技巧:修改Conda环境目录,节省系统盘空间
  • 【每天学点‘音视频’】前向纠错 和 漏包重传
  • vue从入门到精通:搭建第一个vue项目
  • 表格内容对比及标记
  • PLC无线组网实现多台RGV搬运机器人输送系统通讯案例
  • SSM从入门到实战:1.4 Spring Bean的生命周期管理
  • 【STM32】STM32H750 CubeMX 配置 USB CDC 虚拟串口笔记
  • ThinkPHP的安装运行和调试
  • MCP协议演进:从SSE到Streamable HTTP的技术革命
  • SAP ABAP IS SUPPLIED
  • 【语法糖】什么是语法糖
  • Java+Vue构建资产设备管理系统,适配移动端与后台管理,实现全生命周期管理,涵盖采购、入库、使用、维护、报废等环节,提供完整源码,便于二次开发
  • 快速搭建项目(若依)
  • CentOS 7 LAMP快速部署WordPress指南
  • linux中的hostpath卷、nfs卷以及静态持久卷的区别
  • python+flask后端开发~项目实战 | 博客问答项目--数据库信息的基本配置与UserModel的创建,映射,关联
  • 【MySQL】超详细入门学习
  • Linux 系统(如 Ubuntu / CentOS)阿里云虚拟机(ECS)上部署 Bitnami LAMP
  • 【Python】Python Socket 网络编程详解:从基础到实践​
  • 云原生俱乐部-mysql知识点归纳(1)
  • 【前端面试题】JavaScript 核心知识点解析(第十四题解析到第二十二题)
  • 【牛客刷题】正六边形阴影面积计算
  • FastRTSP介绍
  • 微电网管控系统中python多线程缓存与SQLite多数据库文件连接池实践总结(含源码)