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

js设计模式-职责链模式

一. 概览

定义:目的是将请求发送者与接受者解耦,请求会沿着一条链传递,直到有对象处理它。
角色:1. 抽象处理者(Handler):定义处理请求的接口,并维护对下一个处理者的引用。
2. 具体处理者(Concrete Handler):实现请求处理逻辑,判断是否处理或传递给下家。
3. 客户端(Client):组装链并触发请求

核心思想
请求无需直接指定处理者,而是依次传递给链中的每个对象。每个处理者可自行决定是否处理请求(如检查条件或层级),若无法处理,将请求传给链中的下一个处理者。
最后可能返回默认结果(如未处理)。

二. 代码示例

// 抽象处理者
class Handler {constructor() {this.nextHandler = null; // 当前处理者的下一个节点}// 抽象方法:由子类实现具体逻辑handleRequest(request) {if (this.nextHandler) {return this.nextHandler.handleRequest(request);}return `Request '${request}' not handled by any handler.`;}// 设置下一个处理者setNext(handler) {this.nextHandler = handler;return handler; // 支持链式调用}
}// 具体处理者
class DebugHandler extends Handler {handleRequest(request) {debugger;if (request.level === 'DEBUG') {return `DEBUG: ${request.message}`;}// 否则传递给下一个处理者return super.handleRequest(request);}
}// 处理INFO级别的日志
class InfoHandler extends Handler {handleRequest(request) {if (request.level === 'INFO') {return `INFO: ${request.message}`;}return super.handleRequest(request);}
}// 处理ERROR级别的日志
class ErrorHandler extends Handler {debugger;handleRequest(request) {if (request.level === 'ERROR') {return `ERROR: ${request.message}`;}return super.handleRequest(request);}
}// 客户端代码
// 创建各处理者实例
const debugHandler = new DebugHandler();
const infoHandler = new InfoHandler();
const errorHandler = new ErrorHandler();// 构建处理链:DEBUG → INFO → ERROR
debugHandler.setNext(infoHandler).setNext(errorHandler);// 发送不同请求测试链的处理能力
console.log(debugHandler.handleRequest({ level: 'DEBUG', message: 'System initialized' }));
// 输出:DEBUG: System initializedconsole.log(debugHandler.handleRequest({ level: 'INFO', message: 'User signed in' }));
// 输出:INFO: User signed inconsole.log(debugHandler.handleRequest({ level: 'ERROR', message: 'Null reference' }));
// 输出:ERROR: Null referenceconsole.log(debugHandler.handleRequest({ level: 'WARNING', message: 'Disk space low' }));
// 输出:Request 'WARNING' 

三.核心知识点

链式构建过程分析:

  1. 第一步赋值
debugHandler.setNext(infoHandler)

debugHandler 的 nextHandler 被设置为 infoHandler;
返回值是 infoHandler,作为下一步调用的起点
2.第二步赋值(在返回的 infoHandler 上继续)

infoHandler.setNext(errorHandler)

infoHandler 的 nextHandler 被设置为 errorHandler;
最终形成链 debugHandler.nextHandler = infoHandler→ infoHandler.nextHandler = errorHandler → errorHandler.nextHandler = null。

debugHandler.handleRequest({ level: 'WARNING', ... })├─ DebugHandler.check(...) → 不匹配├─ 调用 `super.handleRequest` → 转向 `debugHandler.nextHandler = infoHandler`│└─ InfoHandler.check(...) → 不匹配└─ 调用 `super.handleRequest` → 转向 `infoHandler.nextHandler = errorHandler`│└─ ErrorHandler.check(...) → 不匹配└─ 调用 `super.handleRequest` → 转向 `errorHandler.nextHandler = null`└─ 返回默认错误提示

四. this指向

class makeDrink {constructor() {this.age = 18}handleRequest() {console.log(this.age, 'checkAge')}
}class makeTea extends makeDrink {constructor() {super();this.age = 19}handleRequest() {super.handleRequest();}
}const teaData = new makeTea();
teaData.handleRequest();

为什么打印的是19,super不是继承的父类吗?

原因是:
子类 MakeTea 的构造函数首先通过 super() 调用了父类 MakeDrink 的构造函数
父类构造函数为当前实例(this)设置了 age = 18
子类构造函数在父类初始化完成后,通过 this.age = 19 覆盖了父类设置的属性值
当调用 super.handleRequest() 时:
this 指针仍然指向子类实例
访问的是当前实例的 age 属性(已经被子类修改为19)
关键点:
JavaScript 的继承机制中:

子类实例的属性是直接存储在该实例本身(而不是父类实例)
子类可以覆盖父类在构造函数中设置的属性
super. 语法调用的是父类的方法,但方法内部使用的是子类实例的当前属性值

五. 总结

优点

  1. 解耦请求与处理者:发送者无需知道具体处理者是谁。
  2. 动态配置链:可以在运行时动态调整链中的处理顺序或增减节点。
  3. 扩展灵活:新增处理者不影响现有链,只需实现handleRequest和插入链中。

适用场景
1.多对象可能处理同一个请求。
2.处理顺序需要动态调整。
4. 需隐藏接收者,由链决定传递路径。
比如:
日志分级
DEBUG → INFO → WARNING → ERROR 不同级别由对应处理器过滤。
权限验证
用户请求逐层验证角色、组织、ID权限。
命令调度
接收器将未识别的指令传递给下一个可用处理器。


文章转载自:

http://uwyDD8YS.jxhLx.cn
http://Qy9lduiJ.jxhLx.cn
http://bSMi2Z6p.jxhLx.cn
http://HeaVCQ89.jxhLx.cn
http://BrnUzhf0.jxhLx.cn
http://JigWxoCL.jxhLx.cn
http://5HFkdymj.jxhLx.cn
http://wFmZMEcW.jxhLx.cn
http://n1KQWRcU.jxhLx.cn
http://khbThRR0.jxhLx.cn
http://HxEBrVZe.jxhLx.cn
http://KkBpzHIW.jxhLx.cn
http://kpFXPQtO.jxhLx.cn
http://hl0N8q19.jxhLx.cn
http://vhpBJxF4.jxhLx.cn
http://JMFulT84.jxhLx.cn
http://ygdPWIPu.jxhLx.cn
http://K3NgqXjc.jxhLx.cn
http://RLE3ZSLB.jxhLx.cn
http://g8W5H8pa.jxhLx.cn
http://01373pV1.jxhLx.cn
http://9XhFMJXT.jxhLx.cn
http://oRyF3y50.jxhLx.cn
http://g4niolur.jxhLx.cn
http://Hzq0Fa2K.jxhLx.cn
http://W21r5hFD.jxhLx.cn
http://PFxjoa8G.jxhLx.cn
http://pP21GiMk.jxhLx.cn
http://jxc0pVh5.jxhLx.cn
http://VknHxPir.jxhLx.cn
http://www.dtcms.com/a/363335.html

相关文章:

  • 【音视频】Opus 编码格式介绍
  • WPF应用程序资源和样式的使用示例
  • HarmonyOS 应用开发新范式:深入剖析 Stage 模型与 ArkUI 最佳实践
  • 基于vue3和springboot框架集成websocket
  • 网络数据包是怎么在客户端和服务端之间进行传输的?
  • C#实现与西门子S7-1200_1500 PLC通信
  • qt QWebSocket详解
  • 系统扩展策略
  • 【LeetCode_26】删除有序数组中的重复项
  • 小迪web自用笔记24
  • GPT-5论文选题实测:如何从2000篇文献中提炼出3个可快速落地的高命中选题?
  • 从零开始学Vue3:Vue3的生命周期
  • Leetcode二分查找(4)
  • 开悟篇Docker从零到实战一篇文章搞定
  • 洗衣店小程序的设计与实现
  • GDB 调试
  • 深度学习篇---DenseNet网络结构
  • Spring Boot手写10万敏感词检查程序
  • C#----异步编程
  • 基于Django的论坛系统设计与实现(代码+数据库+LW)
  • Qt模型/视图编程详解:QStringListModel与多视图数据同步
  • 链表题类型注解解惑:理解Optional,理解ListNode
  • 前端实现解析【导入】数据后调用批量处理接口
  • GaussDB 等待事件为LockMgrLock处理方法
  • 为什么程序员总是发现不了自己的Bug?
  • flutter踩坑插件:Swift架构不兼容
  • 疯狂星期四文案网第58天运营日记
  • 手撕Redis底层2-网络模型深度剖析
  • 【3D 入门-4】trimesh 极速上手之 3D Mesh 数据结构解析(Vertices / Faces)
  • Valkey vs Redis详解