策略模式
策略模式:把可互换的算法族封装为同一契约,使调用者能按情境选择行为
直觉:从变化压力出发,而不是从模式名称出发
把价格分支继续堆在结算函数里,会让每次营销变化都触碰主流程 因此,策略模式 的第一步不是画类图,而是写清 结算服务要在不改订单流程的前提下切换普通、会员和大促定价 中哪项变化会扩散、现有结构怎样承担成本,以及什么观察足以拒绝模式。
在实验前先预测:沿 提交订单 → 选择策略 → 执行报价 → 核对约束 → 返回金额 运行时,哪条依赖最先暴露变化;随后只调整一个参与者或连接,保存代码结果和拒绝原因,最后重置到相同基线。
问题合同与术语
意图。 把可互换的算法族封装为同一契约,使调用者能按情境选择行为。适用边界。 算法会独立变化、调用合同稳定,而且运行时选择确实有业务含义。本页验收不变量是:同一订单输入必须得到可解释且非负的报价。
、、、、、
官方目录结构的逐项解释
下面的目录字段采用 GoF 模式目录的标准描述结构来组织独立讲解。每个字段都要连接当前问题、页面专属实验与练习证据;字段名称出现本身不算覆盖。
模式名称与分类
“策略模式”归入行为型模式,名称只用于定位 把可互换的算法族封装为同一契约,使调用者能按情境选择行为,不能替代问题证据。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
意图
“意图”回答模式想改变什么:把可互换的算法族封装为同一契约,使调用者能按情境选择行为。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
别名
“别名”在本页处理为:没有需要单独记忆的稳定别名;评审时使用目录中的正式名称,避免用近似称呼混淆责任。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
动机
“动机”从具体压力出发:把价格分支继续堆在结算函数里,会让每次营销变化都触碰主流程。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
适用性
“适用性”要求同时满足:算法会独立变化、调用合同稳定,而且运行时选择确实有业务含义。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
结构
“结构”由 PricingContext、PricingStrategy、MemberPricing 以及它们之间的引用方向共同确定。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
参与者
“参与者”逐一说明 PricingContext、PricingStrategy、MemberPricing 谁保存状态、谁发起调用以及谁承担变化。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
协作
“协作”的运行协议是:Context 只提供输入并委托 Strategy,具体策略独立计算且不反向控制流程。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
后果
“后果”必须连同收益和成本记录:新增算法变便宜,但客户端必须理解选择规则,策略数量也需要治理。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
实现
“实现”落地时遵守:用窄接口表达输入输出,把策略选择与策略执行拆成两个可测试步骤。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
示例代码
“示例代码”使用本页 TypeScript 最小切片验证“同一订单输入必须得到可解释且非负的报价”,代码是独立教学示例。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
已知应用
“已知应用”可在这些场景识别:排序器、压缩器、路由策略和定价引擎都常用这一变化轴,但名称相似不构成采用证据。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
相关模式
“相关模式”用于比较边界:状态模式也委托行为,但切换通常由状态机推进;模板方法依赖继承固定骨架。 对“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”先保存基线,再改变一个条件;若出现“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”,就拒绝 策略模式 方案并回到更简单结构。
常见误区与反例
另一个易错点是把结构相似当作语义相同。状态模式也委托行为,但切换通常由状态机推进;模板方法依赖继承固定骨架;比较时必须同时写出谁触发变化、谁持有状态、失败如何传播,以及替代方案是否更小。
术语表
练习与答案
本章小结
策略模式 把“结算服务要在不改订单流程的前提下切换普通、会员和大促定价”收敛为 PricingContext、PricingStrategy、MemberPricing 的协作合同。学习结果不是能复述定义,而是能修改代码、触发“只有一个算法或分支从不独立变化时,策略对象只是额外跳转”这一反例、重置实验,并根据 新增算法变便宜,但客户端必须理解选择规则,策略数量也需要治理 接受或拒绝方案。