行为型模式总览
行为型模式组织对象如何协作:算法由谁选择、请求经过谁、状态何时改变、操作如何记录。先定位变化的规则,再选择结构。分支多不是必须引入模式的理由,关键是变化是否需要独立维护和验证。
沿一个导出任务理解协作
创建订单导出时,请求先经过权限、参数等检查,任一检查拒绝就停止,适合用责任链表达。确认合法后,用策略选择 CSV 或其他格式的生成算法;若不同格式都遵循“读取、转换、写出、收尾”的共同骨架,又可以用模板方法组织扩展点。策略选择可替换行为,模板方法固定局部步骤,两者回答的问题不同。
耗时导出可以封装为命令,由调度器执行,但命令对象本身不提供持久队列或防重复执行。任务从待处理变为执行中、成功或失败,状态模式帮助管理允许的操作;真正防止两个工作进程同时完成任务,还需要持久化版本或条件更新。
任务完成后,可以用观察者通知日志、页面刷新等订阅者。进程内回调不等于可靠消息:如果必须在崩溃后补发通知,就要有事件持久化、幂等与重试机制。相关边界见事件驱动架构。
按变化类型阅读
| 要解决的变化 | 阅读入口 | 先确定什么 |
|---|---|---|
| 同一目标有不同算法 | 策略 | 输入输出合同、选择规则与未知类型处理 |
| 固定流程中的局部步骤不同 | 模板方法 | 步骤顺序、必经步骤与资源收尾 |
| 一个变化触发多个订阅者 | 观察者 | 通知顺序、异常隔离与取消订阅 |
| 遍历集合而不暴露存储结构 | 迭代器 | 结束条件、修改与并发语义 |
| 多个节点决定处理或继续 | 责任链 | 顺序、短路与每次请求的推进状态 |
| 对象行为受生命周期约束 | 状态 | 合法转移、重复操作与并发更新 |
| 操作需要调度、记录或重放 | 命令 | 操作身份、结果与幂等 |
| 需要恢复某个对象的历史状态 | 备忘录 | 快照范围、容量与恢复版本 |
| 需要解释受限表达式 | 解释器 | 语法、输入限制与执行预算 |
| 节点种类稳定,操作持续增加 | 访问者 | 分派方式、遍历归属与新节点成本 |
| 多个对象互相调用难以管理 | 中介者 | 协调边界与防止中心对象膨胀 |
迭代器与访问者可以协作:前者负责“依什么顺序访问元素”,后者负责“对不同种类元素做什么”。解释器通常在语法树上求值;面对复杂语法应使用成熟解析工具,不把字符串拆分或执行任意脚本当作通用规则引擎。
用失败反例校验边界
促销策略必须明确金额单位、适用门槛和结果范围。订单金额不足减免额时不能算出负数;未知策略也不能悄悄退回原价。策略注册、类型选择与结果合同都需要验证,不是拆出几个类就自动安全。
订单取消同样需要状态合同。“支付已受理”“退款处理中”“退款成功”是不同事实,不能调用退款接口后立即把订单标为已退款或最终取消。重试、重复回调与并发取消必须按业务协议处理,状态类本身不是分布式事务。
命令撤销与备忘录恢复也有边界。恢复本地编辑器的文字快照,不会撤销已经发出的邮件、删除支付流水或收回他人下载的文件。外部副作用需要新的补偿操作及其结果,不能借“撤销”二字隐藏。
判断设计是否有帮助
沿一次请求,应该能找到算法选择入口、处理顺序、状态持有者和失败去向。再尝试增加一种合法变化,观察修改是否局限于对应扩展点,并验证已有合同。若需要跨多个模式对象来回追踪同一条简单规则,减少抽象层通常更清楚。
