模板方法模式和策略模式有什么区别?
简化版
模板方法模式通过继承固定流程骨架,子类重写部分步骤;策略模式通过组合封装不同算法,运行时选择不同策略。简单记:模板方法是“父类定流程”,策略模式是“外部换算法”。
详细版
模板方法模式和策略模式都能封装变化,但变化粒度不同。
模板方法模式:
- 基于继承;
- 流程顺序由父类固定;
- 子类改变流程中的部分步骤;
- 适合流程稳定、步骤变化的场景。
策略模式:
- 基于组合;
- 不同策略是一整套可替换算法;
- 调用方或上下文可以运行时切换策略;
- 适合多种算法互相替换的场景。
例如文件导入都必须按“读取、校验、转换、保存”执行,只是校验和转换不同,适合模板方法。优惠计算有满减、折扣、会员价等多套规则,适合策略模式。
完整版教学
一、两者为什么容易混淆
模板方法模式和策略模式都在处理“变化的行为”。
它们都能避免重复代码,也都能让不同实现拥有不同逻辑。
但它们的设计方向相反:
- 模板方法模式把流程放在父类,变化点交给子类;
- 策略模式把算法封装成对象,由调用方组合使用。
一个偏继承,一个偏组合。
二、模板方法模式固定流程
模板方法模式适合流程顺序不能乱的场景。
例如数据导入:
读取文件 -> 校验数据 -> 转换数据 -> 保存数据 -> 记录结果
不同文件类型的校验和转换不一样,但整体顺序必须一致。
这时父类定义:
public final void importData() {
read();
validate();
transform();
save();
}
子类只能实现 validate()、transform() 等步骤。
三、策略模式替换算法
策略模式适合一整套算法互相替换。
例如排序:
- 快速排序;
- 归并排序;
- 堆排序。
调用方选择某个排序策略即可,不一定存在统一的父类流程。
策略模式更强调运行时切换:
SortStrategy strategy = factory.get(type);
strategy.sort(data);
四、继承和组合带来的差异
模板方法依赖继承,优点是流程约束强,缺点是父子类耦合强。
策略模式依赖组合,优点是灵活,可以运行时替换,缺点是流程约束弱,需要额外选择策略。
所以如果面试官问“哪个更灵活”,一般可以说策略模式更灵活;如果问“哪个更能保证流程顺序”,模板方法更合适。
五、两者可以结合使用
真实项目里经常组合使用。
例如一个导入框架使用模板方法固定导入流程,但其中“数据校验”这一步可以再委托给不同校验策略。
模板方法:固定导入流程
策略模式:替换某一步的校验算法
这样既保证主流程稳定,又让局部算法可组合。
六、继承骨架与组合算法的选择
固定 5 步流程只变其中 2 步时模板方法较自然;若 4 套算法需要在一次请求中动态切换,策略对象更合适。
template: base skeleton -> subclass hooks; strategy: Context -> injected algorithm
这里真正需要保护的是父类掌握的流程不变量:客户端只能进入模板入口,子类只能改写约定好的步骤。评审时应逐步标出哪些行为固定、哪些行为必须实现、哪些行为只是可选钩子,避免父类和子类互相猜测。
七、继承边界与流程契约验证
| 检查维度 | 应确认的内容 |
|---|---|
| 机制正确性 | 区别不能只背“继承与组合”,还要说明变化粒度是局部步骤还是完整算法。 |
| 适用边界 | 模板方法强调固定顺序和代码复用,策略强调行为替换和运行时组合;两者可以在模板的某一步组合使用。 |
| 测试证据 | 对两种实现运行同一父类契约测试,验证固定步骤顺序一致,再分别验证各自变化步骤 |
| 工程代价 | 重点评估父类改动会影响多少子类、protected 扩展面有多大,以及新增变化是否迫使无关子类一起修改 |
易错点:区别不能只背“继承与组合”,还要说明变化粒度是局部步骤还是完整算法。
八、常见误区与追问
- 误区:策略模式完全不能复用公共流程。 策略实现可组合公共服务或委托共享组件,只是不依赖父类固定骨架来复用。
- 误区:模板方法要求所有步骤都由子类覆写。 稳定步骤应在父类直接实现;只有必要变化点才做抽象步骤,可选变化点才做有默认实现的钩子。
- 追问:什么时候从模板方法重构成策略? 当子类数量膨胀、需要运行时切换或出现多个独立变化维度时,应把变化行为提成组合对象。
- 追问:模板方法为什么常声明为 final? 为了防止子类改写算法骨架和步骤顺序;若框架有意允许重写,则必须明确不变量和扩展契约。
- 追问:模板方法最关键的回归测试是什么? 是父类契约测试:所有子类都必须满足固定步骤顺序、公共前后置行为和异常清理规则。
九、加强记忆
模板方法和策略模式的区别记成“模板方法靠继承定流程,策略模式靠组合换算法”。流程稳定、局部步骤变化用模板方法;算法整体可替换、需要运行时切换用策略模式。