行为型设计模式
本页按场景选择方法;通过各条目链接阅读完整推演、源码和输出。
每个 package main 是独立 main.go,需在模块中分别保存;本轮仅静态推导输出,未执行。传入的策略、步骤、监听函数和接口对象必须非 nil;Iterator.Index 要保持在 0..len(Values),解释器表达式树有限无环。示例均在单个 goroutine 中调用,不能自动视为线程安全。
| 要解决的问题 | 可选方法 | 选择前确认 |
|---|---|---|
| 替换整段算法,或只替换稳定流程中的步骤 | 策略或模板方法 | 策略注入计算规则;模板方法固定步骤顺序,Go 可用函数参数与组合表达。 |
| 对象随当前状态改变行为 | 状态 | 状态类型承载各自行为,转换规则需明确并排除非法转换。 |
| 让请求依次校验,或先保存请求稍后执行 | 职责链或命令 | 职责链关注顺序和短路;命令封装动作与参数,撤销还需反向操作或旧状态。 |
| 变化时通知多个订阅方,或协调多个组件 | 观察者或中介者 | 观察者示例同步通知,会被慢回调阻塞;中介者集中协调,需防止职责膨胀。 |
| 保存编辑历史并恢复 | 备忘录 | 值快照可恢复文本;含切片、映射或外部资源时需明确复制语义和成本。 |
| 隐藏集合存储,或在稳定对象结构上新增操作 | 迭代器或访问者 | 普通切片可直接 range;访问者增加操作方便,但新增元素类型需修改全部访问者。 |
| 递归求值规则有限的表达式 | 解释器 | 简单语法树可自行组合;优先级、变量与错误恢复变复杂时应采用正式解析器。 |
替换计算规则、流程步骤与状态行为
策略
正文、推演与完整示例:策略。
只有一种固定规则时,不必为策略额外设计接口层。
模板方法
正文、推演与完整示例:模板方法。
流程的固定部分必须稳定,否则频繁增加钩子会让模板难以理解。
状态
正文、推演与完整示例:状态。
转换规则需要集中定义,并保证不允许的转换不会悄悄发生。
顺序处理校验并封装待执行请求
职责链
正文、推演与完整示例:职责链。
若处理器会修改请求,应把执行顺序和错误传播方式定义清楚。
命令
正文、推演与完整示例:命令。
需要撤销时,命令还要保存反向操作或执行前的状态。
通知订阅者与协调组件通信
观察者
正文、推演与完整示例:观察者。
这个同步版本会被慢回调阻塞;生产场景还要考虑退订、异常隔离和并发安全。
中介者
正文、推演与完整示例:中介者。
中介者也可能膨胀成过大的协调中心,需要保持职责清晰。
保存对象快照并恢复历史状态
备忘录
正文、推演与完整示例:备忘录。
真实对象含有切片、映射或外部资源时,快照成本与复制语义需要明确。
遍历集合、扩展对象操作与求值表达式
迭代器
正文、推演与完整示例:迭代器。
对普通切片直接使用 range 更简单;自定义容器或惰性数据源才更需要独立迭代器。
访问者
正文、推演与完整示例:访问者。
新增元素类型却要求所有访问者增加方法,因此它适合元素种类相对稳定的结构。
解释器
正文、推演与完整示例:解释器。
规则一旦出现优先级、变量和错误恢复等需求,就应使用正式解析器。
静态自检
观察者第一个回调一直不返回,第二个会收到事件吗?提示:Publish 逐个同步调用。
参考解法
不会;后一个回调须等前一个返回。若需要异步隔离,应另定义顺序、容量、错误、退订和退出协议,不能简单加 goroutine 后继续承诺原有通知顺序。
继续阅读
- 设计意图与对象责任
- 设计意图与对象责任
- 设计意图与对象责任