当前位置: 首页 > news >正文

Java 23 种设计模式:从踩坑到精通 | 番外:策略 vs 模板方法 —— 组合与继承的终极对决

Java 23 种设计模式:从踩坑到精通 | 番外:策略 vs 模板方法 —— 组合与继承的终极对决

摘要:策略模式和模板方法模式都能消除重复代码,但策略用“组合”替换整体算法,模板方法用“继承”固定算法骨架。它们的核心区别在于控制权的归属——策略模式由客户端选择算法,模板方法由父类控制流程。本文从电商促销和数据同步两个实战场景出发,结合代码对比、UML 分析和 JDK 源码,带你彻底理解“组合优于继承”的真正含义。

🗺️本文阅读地图(3 分钟速览)

  • 为什么策略和模板方法都能消除重复?它们到底像在哪里?
  • UML 对比:接口+组合 vs 抽象类+继承
  • 手写促销策略引擎 vs 数据同步模板,感受差异
  • DKComparator(策略) vsHttpServlet(模板方法)源码对比
  • 面试必问:“什么时候用策略?什么时候用模板方法?”

📖《Java 23 种设计模式:从踩坑到精通》
开篇:系列介绍与目录 |当前:番外 · 策略 vs 模板方法
🔗 返回系列总目录


文章目录

  • Java 23 种设计模式:从踩坑到精通 | 番外:策略 vs 模板方法 —— 组合与继承的终极对决
    • 1. 从“电商促销”和“数据同步”两个场景说起
      • 1.1 场景一:电商促销(策略模式)
      • 1.2 场景二:数据同步(模板方法模式)
    • 2. UML 对比:接口+组合 vs 抽象类+继承
      • 2.1 策略模式 UML(组合)
      • 2.2 模板方法模式 UML(继承)
    • 3. 四大核心区别
    • 4. JDK 源码对比
      • 4.1 `Comparator`(策略模式)
      • 4.2 `HttpServlet`(模板方法模式)
    • 5. 面试必问 + 追问连环炮
    • 🧭 《Java 23 种设计模式:从踩坑到精通》快速导航

1. 从“电商促销”和“数据同步”两个场景说起

1.1 场景一:电商促销(策略模式)

电商系统有多种促销算法——满减、打折、立减。不同活动、不同用户可能使用不同的促销策略。这些算法整体可替换,你需要在运行时灵活选择用哪种促销。

// 策略模式:客户端选择算法Orderorder=newOrder(500);order.setPromotionStrategy(newFullReductionStrategy());// 满减doubleprice1=order.checkout();order.setPromotionStrategy(newDiscountStrategy());// 切换打折doubleprice2=order.checkout();

💬特征:算法之间完全独立,客户端显式选择使用哪个策略。

1.2 场景二:数据同步(模板方法模式)

不同数据源的同步流程大体相同——连接、抽取、转换、加载、断开。这些步骤的流程固定,但“抽取什么数据”、“怎么转换”各不相同。

// 模板方法模式:父类固定流程,子类填空publicabstractclassDataSyncTemplate{publicfinalvoidsync(){// 模板方法:final,防止篡改connect();extractData();// 子类实现transformData();// 钩子:可选覆盖loadData();// 子类实现disconnect();}// ...}

💬特征:流程骨架固定,子类只能填空,不能改变顺序。


2. UML 对比:接口+组合 vs 抽象类+继承

2.1 策略模式 UML(组合)

2.2 模板方法模式 UML(继承)

UML 的关键差异

  • 策略模式使用接口 + 组合Context持有Strategy引用,由客户端注入;
  • 模板方法模式使用抽象类 + 继承,父类定义骨架,子类通过继承实现可变步骤;
  • 策略的Context提供setStrategy()方法,模板方法的父类不提供切换方法——因为骨架是固定的。

3. 四大核心区别

对比维度策略模式模板方法模式
核心机制接口 + 组合抽象类 + 继承
控制权客户端选择算法父类控制流程,子类只填空
替换粒度整个算法可替换算法骨架固定,部分步骤可变
复用方式复用策略类(组合)复用父类通用代码(继承)
典型应用Comparator、支付方式HttpServletJdbcTemplate

💡简单记忆:策略是“组合替换”——整个算法随便换;模板方法是“继承填空”——骨架固定,填细节。


4. JDK 源码对比

4.1Comparator(策略模式)

// Comparator 是策略接口,每种排序规则是一个具体策略List<String>list=Arrays.asList("apple","banana","cherry");list.sort(Comparator.naturalOrder());// 正序策略list.sort(Comparator.reverseOrder());// 倒序策略list.sort(Comparator.comparing(String::length));// 按长度策略

💬 客户端显式选择排序策略,策略之间完全独立。

4.2HttpServlet(模板方法模式)

// HttpServlet 是模板父类,service() 是模板方法publicclassMyServletextendsHttpServlet{@OverrideprotectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp){// 只填空:处理 GET 请求}@OverrideprotectedvoiddoPost(HttpServletRequestreq,HttpServletResponseresp){// 只填空:处理 POST 请求}}

💬service()方法是final的,流程固定——子类不能改变“先判断方法类型再分发”的骨架。


5. 面试必问 + 追问连环炮

基础必问

  • 策略模式和模板方法模式的区别?
    👉 策略用组合替换整体算法(客户端选择),模板方法用继承固定骨架(父类控制流程)。
  • 什么时候用策略?什么时候用模板方法?
    👉 算法整体可替换、需要灵活组合 → 策略;流程固定、只有部分步骤不同 → 模板方法。

面试官追问

  • “为什么说策略模式体现了‘组合优于继承’?”
    👉 策略通过接口+组合来替换算法,可以在运行时动态切换;继承只能在编译时确定,且子类受限于父类的骨架设计。组合比继承更灵活。
  • “模板方法模式中钩子方法的作用?”
    👉 钩子方法提供默认实现,子类可选覆盖。它让父类在固定流程中留出“可开关的分支”——例如wantCondiments()控制是否加调料,子类重写它就能改变流程行为。
  • JdbcTemplate是策略还是模板方法?”
    👉 模板方法模式。JdbcTemplate固定了“获取连接→执行SQL→处理结果集→释放资源”的流程,用户只通过回调接口填写 SQL 和结果映射逻辑。
  • “策略模式和模板方法能配合使用吗?”
    👉 可以。模板方法固定流程,策略在流程中的某个步骤提供多种算法选择。例如数据同步框架中,extractData()步骤可以用策略模式支持多种数据源(MySQL、PostgreSQL、MongoDB)。

🎉恭喜:如果你能立刻说出Comparator是策略模式(组合替换),HttpServlet是模板方法模式(继承填空),你已经掌握了行为型模式中最核心的“组合 vs 继承”设计哲学。

💡延伸阅读:本文是策略模式与模板方法模式的深度对比。如果你想先了解每种模式的完整原理、UML、代码实现和面试题,可以先阅读正篇——策略模式:算法族的封装与切换,告别 if-else 和 模板方法模式:定义算法骨架,交给子类填充细节,再回来看这篇对比,效果更佳。

🧭 《Java 23 种设计模式:从踩坑到精通》快速导航

  • 开篇:系列介绍与目录
  • 当前:番外 · 策略 vs 模板方法 —— 组合与继承的终极对决(你在这里)
  • 📖 延伸阅读:策略模式正篇 | 模板方法模式正篇
  • 创建型模式汇总
  • 结构型模式汇总
  • 行为型模式汇总

🔔 关注《Java 23 种设计模式:从踩坑到精通》,用 25 篇文章彻底吃透设计模式。
📦福利预告:全系列代码及 UML 源码将在完结时统一打包开放,点击「关注」「收藏」第一时间获取。

📌 除了设计模式,我也在深挖智能物流实战(WMS、托盘调度、机器学习落地)。欢迎点击头像,看看专栏 《出版社物流WMS智能调度实战》。技术相通,思路可鉴。

http://www.jsqmd.com/news/1182443/

相关文章:

  • 计算机毕业设计之基于SpringBoot社区团购系统
  • 如何快速掌握开源火箭发动机模拟器:OpenMotor完整入门指南
  • 猫抓浏览器扩展:网页媒体资源嗅探下载的完整解决方案
  • 如何快速上手keras-resnet:5分钟构建你的第一个ResNet模型
  • 成都卖名表去哪靠谱,全城连锁腕表回收平台,各类奢表当面验表当场结算无套路 - 奢侈品回收评测
  • Kimi-K2-Thinking-W4A8推理优化:vLLM参数调优与性能调优终极指南
  • DeepSeek那把看不见的算盘
  • 常州合规持证收钻门店实测榜单,2026 彻底规避线上低价引流回收套路 - 每日生活报
  • 猫抓浏览器扩展深度解析:网页媒体资源智能嗅探完整指南
  • Gemma-4-E4B-it-8bit模型转换技术:从原始模型到MLX格式的完整流程
  • 3大核心功能彻底解决Windows 10/11经典游戏兼容性问题:dxwrapper完全指南
  • 萧邦中国官方售后服务中心|服务热线及门店详细地址权威信息通知(2026年7月最新) - 萧邦中国官方服务中心
  • Llama-3.1-8B_rai_1.7.1_npu_16K的ONNX运行时配置与优化技巧
  • 如何在AMD NPU上部署Qwen2.5_3B_Instruct_rai_1.7.1_npu_16K?超详细快速入门指南
  • AI进教室vs教师站讲台:未来三年教育岗位正在重新洗牌
  • OBS多路推流插件终极指南:5分钟实现多平台同步直播的完整教程
  • 网页媒体资源智能捕获方案:开源浏览器扩展的技术解析与实践指南
  • 【公众号】baoyu-skills 微信公众号自动编辑与发布机制
  • Origin 数据导入的 7 个坑和 SCI 投稿排版的 5 条红线——不想被退回来就照着检查
  • FIGConvNet DrivAerML Surface:NVIDIA革命性AI模型如何加速汽车空气动力学计算
  • 终极黑苹果配置指南:OpCore-Simplify让OpenCore EFI搭建从复杂到简单
  • AMD Ryzen AI 1.7.1与DeepSeek-R1蒸馏模型的完美结合:性能提升秘籍 [特殊字符]
  • 计算机毕业设计之基于SpringBoot少儿编程网站的设计与开发
  • Java 23 种设计模式:从踩坑到精通 | 番外:工厂方法 vs 抽象工厂 —— 从单产品到产品族,架构如何演进?
  • AMD Ryzen AI生态新成员:Meta-Llama-3.1-8B-Instruct_rai_1.7.1_npu_16K模型评测与前景展望
  • 免费解锁Wand专业版:终极完整指南,告别订阅费
  • 高级技巧:如何微调Qwen2.5-Coder-1.5B-Instruct_rai_1.7.1_npu_4K以适应特定编程语言
  • 如何掌握PHP聚合根(Aggregate Root)设计与实现:state-of-the-union项目的终极指南
  • 【厦门集美区地域拆解】厦门首饰回收哪家正规 公安备案资质可开具书面回收单据 - 讯息早知道
  • 猫抓浏览器扩展:网页媒体资源一键获取的终极解决方案