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

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://www.xdnf.cn/news/19746.html

相关文章:

  • More Effective C++ 条款24:理解虚拟函数、多继承、虚继承和RTTI的成本
  • VMWare ubuntu24.04安装(安装ubuntu安装)
  • 复杂PDF文档如何高精度解析
  • css3元素倒影效果属性:box-reflect
  • IsaacLab训练机器人
  • uni-app 实现做练习题(每一题从后端接口请求切换动画记录错题)
  • 国内免费低代码软件精选:四款工具助你快速开启数字化转型之路
  • 力扣72:编辑距离
  • windows docker(二) 启动存在的容器
  • 5招教你看透PHP开发框架的生态系统够不够“牛”?
  • 推荐一个论文阅读工具ivySCI
  • latex怎么写脚注:标共一声明,标通讯作者
  • 使用 Avidemux 去除视频的重复帧
  • 从实操到原理:一文搞懂 Docker、Tomcat 与 k8s 的关系(附踩坑指南 + 段子解疑)
  • 血缘元数据采集开放标准:OpenLineage Guides 在 Spark 中使用 OpenLineage
  • SpringBoot3中使用Caffeine缓存组件
  • 模版进阶及分离编译问题
  • ansible判断
  • 科学研究系统性思维的方法体系:数据分析模板
  • C语言:归并排序和计数排序
  • OCR识别在媒资管理系统的应用场景剖析与选择
  • 基于ZooKeeper实现分布式锁(Spring Boot接入)及与Kafka实现的对比分析
  • Pod自动重启问题排查:JDK 17 EA版本G1GC Bug导致的应用崩溃
  • Element Plus 表格表单校验功能详解
  • 【Web前端】JS+DOM来实现乌龟追兔子小游戏
  • 轻型载货汽车变速器设计cad+设计说明书
  • 【序列晋升】25 Spring Cloud Open Service Broker 如何为云原生「服务市集」架桥铺路?
  • 分布式光纤传感选型 3 问:你的场景该选 DTS、DAS 还是 BOTDA?
  • 2017考研数学(二)真题
  • vue2滑块验证