Skip to content

参考 ​

基于 Refactoring.Guru + Node.js v26 / XState v5 / MDN 迭代协议官方文档编写

速查 ​

  • 行为型 10 模式:责任链 / 命令 / 迭代器 / 中介者 / 备忘录 / 观察者 / 状态 / 策略 / 模板方法 / 访问者
  • 关注:对象间职责分配 + 通信算法(不涉及创建与结构装配)
  • JS 语言级内置:迭代器 Symbol.iterator、观察者 EventEmitter / EventTarget
  • XState v5:createMachine + createActor().start()(替代 v4 interpret)
  • undo/redo:双栈 + execute 前 saveBackup + 新命令清空 redoStack
  • 策略 vs 状态:策略由客户端切换 / 状态由状态对象自身切换
  • 责任链:setNext 返回 handler 支持链式,ConcreteHandler 要么处理要么传递
  • 访问者:双分派 accept(v) 内 v.visitXxx(this),Babel/ESLint 插件即此模式
  • 详尽讲解见 入门 / 十模式深度讲解

十模式完整对比表 ​

模式意图(一句话)关键角色前端典型落地主要反模式
责任链请求沿链传递,每个 Handler 决定处理或转交Handler / ConcreteHandler / ClientExpress/Koa middleware、axios interceptors链断裂(既不处理也不传递)
命令把请求封装成对象,支持 undo/redo 与排队Command / ConcreteCommand / Receiver / Invoker / History富文本 undo/redo、Redux dispatch单栈无法 redo、execute 前未 saveBackup
迭代器提供统一协议顺序遍历集合Iterable [Symbol.iterator]() / Iterator next()→{value,done}for...of / Generator / Map/Set/Array共享迭代器实例致状态互踩
中介者用中心对象协调多组件,消除网状依赖Mediator / ConcreteMediator / ComponentVue 3 mitt、对话框协调、Pinia 宏观中介God Mediator(中介者膨胀)
备忘录不破坏封装下保存与恢复对象内部状态Originator / 不可变 Memento / Caretaker编辑器撤销、表单草稿、游戏存档不限制历史长度致快照栈爆炸
观察者一对多依赖,目标变化自动通知所有订阅者Publisher / SubscriberEventEmitter / Redux store.subscribe / mitt / EventTarget未取消订阅致内存泄漏、通知风暴
状态状态变化时行为也跟着变,状态封装成独立类Context / State / ConcreteStateXState v5 状态机、订单/审批流、TCP 状态巨型 switch-case + 布尔标志位
策略一族可互换算法封装成独立类,运行时切换Context / Strategy / ConcreteStrategy表单校验器、排序规则、价格计算1-2 个变体硬套类层次(过度设计)
模板方法父类定义算法骨架,子类重写个别步骤AbstractClass(模板方法 + 抽象/可选/钩子步骤)/ ConcreteClassReact 类组件生命周期、构建管线子类重写模板方法破坏骨架
访问者不修改类的前提下为其新增操作(双分派)Element accept(v) / Visitor visitXxx(this)Babel/ESLint AST 插件、编译器语义分析用于变动结构(维护成本爆炸)

易混模式对比 ​

策略 vs 状态(最高频考点) ​

维度策略状态
状态间感知互不感知可相互感知
主动切换方客户端 setStrategy()状态对象自身 context.changeState()
行为意图算法可互换状态驱动行为切换
数量可任意多通常有限(订单状态、连接状态等)
转换规则无有(甚至有守卫 guards)
典型场景表单校验、排序订单流、TCP 连接、视频播放器

中介者 vs 观察者 ​

维度中介者观察者
通信方式集中式(中心对象协调)分布式(发布者广播)
组件感知中介者知道每个组件身份只关心事件订阅
协调逻辑封装在中介者内部散落在订阅者
适用场景组件交互复杂、强协调跨组件解耦广播
关系与观察者可混合(EventBus)独立

责任链 vs 装饰器(结构型) ​

维度责任链(行为型)装饰器(结构型)
流向可中断不可中断
意图分发职责增强功能
顺序决定处理或传递全程包裹

模板方法 vs 策略 ​

维度模板方法策略
机制继承(重写方法)组合(持策略引用)
切换时机类级静态(编译期定)运行时可切换
骨架父类固定骨架无骨架概念
粒度整个算法流程单一算法

命令 vs 备忘录(undo 实现) ​

维度命令备忘录
关注操作的执行 + 撤销状态的保存 + 恢复
undo 实现execute() 反向操作restore 快照
配合命令常当 Caretaker备忘录提供快照存储

前端映射速查表 ​

模式库 / 框架 / API映射点
观察者Node.js EventEmitteron/emit/once/off
观察者Redux store.subscribe拉模型 + getState
观察者浏览器 EventTarget / mitt / nanoevents事件总线
迭代器ES2015 Symbol.iterator + for...of语言级内置
迭代器Generator function* / yield迭代器语法糖
状态XState v5 createMachine / createActor状态机工程化
责任链Express / Koa middleware next()中间件链
责任链axios interceptors.request.use()拦截器链
命令Redux dispatch({type, payload})命令对象(无 undo 时退化成事件)
策略VeeValidate / Yup / Zod schema表单校验器
访问者Babel @babel/traverse 插件 visitorAST 节点遍历
访问者ESLint 规则 create 方法返回 visitorAST 节点遍历
中介者Pinia / Redux store宏观状态中介者
中介者Vue 3 mitt(替代 Vue 2 event bus)松散事件总线

三种步骤类型(模板方法) ​

步骤类型父类提供子类责任用途
抽象步骤仅声明 abstract必须实现强制子类提供关键步骤
可选步骤默认实现可重写给常见默认值,特殊情况可覆盖
钩子(Hook)空方法 / 默认布尔可选择性覆盖扩展点,默认不影响骨架

双分派图解(访问者) ​

text
普通多态(单分派):
  element.foo() → JS 根据 element 的实际类型调用对应 foo

访问者(双分派):
  element.accept(visitor)
    → 第 1 次分派:根据 element 实际类型决定调 visitUser/visitGroup/...
    → 第 2 次分派:根据 visitor 实际类型(PrintVisitor/ExportVisitor/...)
                  决定执行哪个具体实现

命令模式双栈图解 ​

text
初始:undoStack=[]  redoStack=[]

执行 cmd1:
  cmd1.execute() → undoStack=[cmd1]  redoStack=[]  (清空!)

执行 cmd2:
  cmd2.execute() → undoStack=[cmd1,cmd2]  redoStack=[]

undo:
  pop undoStack=cmd2 → cmd2.undo() → push redoStack
  → undoStack=[cmd1]  redoStack=[cmd2]

redo:
  pop redoStack=cmd2 → cmd2.execute() → push undoStack
  → undoStack=[cmd1,cmd2]  redoStack=[]

undo 后执行新 cmd3:
  → undoStack=[cmd1,cmd3]  redoStack=[]  (清空 redoStack!避免分支错乱)

ES6 迭代协议要点 ​

协议必须用法
Iterable[Symbol.iterator]() 返回 Iteratorfor...of 消费
Iteratornext() 返回 {value, done}手动遍历
Generatorfunction* + yield自动生成符合上述协议的对象
内置 IterableArray / Map / Set / String / TypedArray / NodeList / arguments直接 for...of

关键纪律:[Symbol.iterator]() 每次调用必须返回新迭代器,否则多个消费者共享状态互相踩。

XState v5 关键 API ​

API作用v4 → v5 差异
createMachine({...})声明状态机配置配置项兼容(states/on/target/actions/guards/context)
createActor(machine).start()创建并启动 actor 实例替代 v4 interpret(machine).start()
actor.subscribe(cb)订阅状态变化类似 v4 但返回 ActorSubscription
actor.send({type})发送事件触发转换与 v4 一致
assign(({ctx,event}) => ...)声明式 context 更新与 v4 一致

反模式清单(跨模式) ​

反模式模式后果解法
链断裂责任链请求静默丢失链尾兜底 + 显式 super.handle()
单栈 undo命令无法 redo双栈
execute 前 saveBackup 缺失命令undo 时无状态可恢复强制 execute 第一步抓快照
共享迭代器实例迭代器多消费者互相踩状态每次调用返回新迭代器
God Mediator中介者巨型类膨胀拆多个职责单一中介者
不限制历史长度备忘录快照栈无限增长限制 maxLen + 增量快照
未取消订阅观察者内存泄漏组件卸载必 unsubscribe
通知风暴观察者级联重渲染selector + 浅比较 / RxJS 节流
巨型 switch-case状态非法转换无防护、不可维护XState 声明式状态机
类爆炸(过度设计)策略/状态5+ 文件解决 1 个变体用高阶函数
重写模板方法模板方法破坏骨架一致性约定 + 注释禁重写
Visitor 用于变动结构访问者每加元素改所有 Visitor结构稳定才用 Visitor

版本与生态现状 ​

项取值备注
GoF 行为型模式1994 经典理论,无版本号语言无关、稳定不变
Node.js EventEmitter自 Node v0.1 稳定至今on/emit/once/removeListener 不变
ES6 迭代协议ES2015 标准化永久内置,无替代
XStatev5(v4 已进维护期)createActor 替代 interpret
Redux ToolkitRTK 取代手写 reducer底层 store.subscribe 机制不变
mitt~200B 事件总线Vue 3 推荐
nanoevents极简事件总线~93B
Vue 2 event-bus已移除Vue 3 用 mitt 或 props-down-events-up

官方资源 ​