欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > 策略模式和模板方法模式的区别【面试题】

策略模式和模板方法模式的区别【面试题】

2025/6/19 20:43:03 来源:https://blog.csdn.net/qq_45938780/article/details/148684215  浏览:    关键词:策略模式和模板方法模式的区别【面试题】

策略模式和模板方法模式的区别【面试题】

摘要:
策略模式和模板方法模式均属于行为设计模式,但核心差异显著。策略模式通过组合实现,支持运行时动态切换完整算法(如支付方式切换),变化维度大;模板方法模式通过继承实现,固定算法骨架但允许子类定制特定步骤(如文档生成流程不变,数据源可变),变化维度小。前者由调用方主动选择策略(控制权在客户端),后者遵循“好莱坞原则”由父类控制流程调用子类方法(控制权在父类)。选择依据:需灵活替换整套逻辑用策略模式;需复用流程但微调步骤用模板方法模式。

简单记忆:

第一,机制不同。模板方法靠继承,策略靠组合。这意味着模板方法在编译时就确定了行为扩展(通过子类化)相对变化小,而策略可以在运行时切换,变化的大。

第二,变化维度不同。模板方法变化的是算法中的某些步骤,整体流程不变;策略变化的是整个算法实现。就像做菜,模板方法是固定了“洗菜-切菜-烹饪”流程但允许换刀工,策略则是直接换菜系。

第三,控制方向相反。模板方法由父类控制流程调用子类方法(好莱坞原则),策略是调用方主动选择策略对象。

策略模式(Strategy Pattern)和模板方法模式(Template Method Pattern)都是行为设计模式,都用于封装变化的部分,但它们解决问题的角度、实现机制和适用场景有本质区别。以下是两者核心区别的清晰对比:

1)相同点

策略模式(Strategy Pattern)和模板方法模式(Template Method Pattern)都是行为设计模式,都用于封装变化的部分,但它们解决问题的角度、实现机制和适用场景有本质区别。以下是两者核心区别的清晰对比:

2)不同点

2.1)核心目标不同

  • 策略模式:
    替换整个算法
    目标是定义一系列可互换的算法,让客户端能根据需要动态切换不同的算法实现,且算法的变化不影响使用它的上下文。
    👉 核心:算法的完整替换。
  • 模板方法模式:
    定义算法的骨架,允许子类重写特定步骤
    目标是固定一个操作的整体流程结构,仅允许子类修改流程中的某些步骤(变化点),而不改变算法的主干。
    👉 核心:算法骨架不变,步骤细节可变。

2.2)实现机制不同

特性策略模式模板方法模式
关系类型组合(Has-a)继承(Is-a)
关键参与者Context 持有 Strategy 接口的引用抽象类定义 模板方法 + 抽象步骤方法
扩展方式新增 Strategy 实现类创建子类并实现抽象方法/覆盖钩子方法
运行时行为可动态切换策略对象子类行为在编译时确定(通过继承)
控制流方向Context 委托给策略对象执行父类调用子类方法(“好莱坞原则”)

2.3)变化点不同

  • 策略模式:
    变化的是整个算法逻辑
    例如:支付时在 支付宝信用卡PayPal完全不同的支付逻辑之间切换。
  • 模板方法模式:
    变化的是算法中的某些步骤整体流程固定不变
    例如:文档生成流程 打开模板->填充数据->保存文件 中,填充数据 的方式可变(填数据库数据/API数据),但步骤顺序不变。

2.4)代码结构对比

策略模式伪代码

// 策略接口
interface CompressionStrategy {void compress(File file);
}// 具体策略
class ZipCompression implements CompressionStrategy {void compress(File file) { /* ZIP压缩逻辑 */ }
}class RarCompression implements CompressionStrategy {void compress(File file) { /* RAR压缩逻辑 */ }
}// 上下文(组合策略)
class Compressor {private CompressionStrategy strategy;void setStrategy(CompressionStrategy s) { this.strategy = s; }void compressFile(File file) {strategy.compress(file); // 委托给当前策略}
}// 使用:动态切换策略
Compressor compressor = new Compressor();
compressor.setStrategy(new ZipCompression()); // 运行时切换为ZIP
compressor.compressFile(file);

模板方法模式伪代码

// 抽象类(定义模板骨架)
abstract class DataExporter {// 模板方法 (final 防止子类覆盖流程)public final void export() {openConnection();fetchData();      // 抽象方法 -> 子类实现transformData();  // 钩子方法 -> 子类可选覆盖save();           // 抽象方法 -> 子类实现closeConnection();}protected abstract void fetchData();protected abstract void save();protected void transformData() {} // 默认空实现(钩子方法)private void openConnection() { /* 通用逻辑 */ }private void closeConnection() { /* 通用逻辑 */ }
}// 具体子类
class CSVExporter extends DataExporter {protected void fetchData() { /* 从DB取数据 */ }protected void save() { /* 存为CSV */ }
}class JSONExporter extends DataExporter {protected void fetchData() { /* 从API取数据 */ }protected void save() { /* 存为JSON */ }protected void transformData() { /* 自定义数据转换 */ } // 覆盖钩子
}// 使用:子类继承固定流程
DataExporter exporter = new CSVExporter();
exporter.export(); // 执行固定流程+子类实现的步骤

2.5) 适用场景对比

场景策略模式模板方法模式
算法需要动态切换✅ 支付方式、排序算法、导航策略等❌ 子类行为在编译时绑定
多个类有相同流程但不同步骤✅ 框架生命周期、文档生成、ETL流程
避免重复的流程代码✅ 将通用流程抽取到父类
隐藏算法实现细节✅ 客户端只依赖策略接口❌ 子类需知晓抽象步骤
扩展新算法/行为✅ 新增策略类即可✅ 新增子类实现抽象步骤
控制子类扩展点✅ 用 final 模板方法保护核心流程
关键总结:一句话区分
  • 策略模式“换整套方案”
    → 通过组合动态切换完整算法(如支付时换整套支付逻辑)。
  • 模板方法模式“固定流程,定制步骤”
    → 通过继承固定算法骨架,子类定制某些步骤(如报告生成流程固定,但数据来源和格式可定制)。

💡 简单记忆

  • 需要运行时灵活替换整个算法?→ 策略模式(组合)。
  • 需要复用固定流程但允许步骤自定义?→ 模板方法模式(继承)。

喜欢我的文章记得点个在看,或者点赞,持续更新中ing…

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词