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

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

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

  • 为什么策略和模板方法都能消除重复?它们到底像在哪里?
  • UML 对比:接口+组合 vs 抽象类+继承
  • 手写促销策略引擎 vs 数据同步模板,感受差异
  • DK Comparator(策略) vs HttpServlet(模板方法)源码对比
  • 面试必问:"什么时候用策略?什么时候用模板方法?"
    📖 《Java 23 种设计模式:从踩坑到精通》

开篇:系列介绍与目录 | 当前:番外 · 策略 vs 模板方法

🔗 返回系列总目录


文章目录

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

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

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

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

java 复制代码
// 策略模式:客户端选择算法
Order order = new Order(500);
order.setPromotionStrategy(new FullReductionStrategy());  // 满减
double price1 = order.checkout();

order.setPromotionStrategy(new DiscountStrategy());       // 切换打折
double price2 = order.checkout();

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

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

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

java 复制代码
// 模板方法模式:父类固定流程,子类填空
public abstract class DataSyncTemplate {
    public final void sync() {      // 模板方法: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.1 Comparator(策略模式)

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

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

4.2 HttpServlet(模板方法模式)

java 复制代码
// HttpServlet 是模板父类,service() 是模板方法
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        // 只填空:处理 GET 请求
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
        // 只填空:处理 POST 请求
    }
}

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


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

基础必问

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

面试官追问

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

🎉 恭喜 :如果你能立刻说出 Comparator 是策略模式(组合替换),HttpServlet 是模板方法模式(继承填空),你已经掌握了行为型模式中最核心的"组合 vs 继承"设计哲学。
💡 延伸阅读 :本文是策略模式与模板方法模式的深度对比。如果你想先了解每种模式的完整原理、UML、代码实现和面试题,可以先阅读正篇------策略模式:算法族的封装与切换,告别 if-else模板方法模式:定义算法骨架,交给子类填充细节,再回来看这篇对比,效果更佳。

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

🔔 关注《Java 23 种设计模式:从踩坑到精通》,用 25 篇文章彻底吃透设计模式。

📦 福利预告:全系列代码及 UML 源码将在完结时统一打包开放,点击「关注」「收藏」第一时间获取。
📌 除了设计模式,我也在深挖智能物流实战 (WMS、托盘调度、机器学习落地)。欢迎点击头像,看看专栏 《出版社物流WMS智能调度实战》。技术相通,思路可鉴。

相关推荐
库克克1 小时前
【C++】类和对象--this指针详解
java·开发语言·c++
SL_staff2 小时前
JVS低代码完整源码解析:如何二次开发自己的表单组件?
java·低代码·vuex
QN1幻化引擎2 小时前
Gravity-Anchored Cognitive Field Architecture: The DalinX V8/V10 Implementation
java·前端·算法
一生有你20202 小时前
Spring AI ChatMemory 监控与排查:从指标到排错全链路
java·人工智能·spring
程序员黎剑2 小时前
我把算卦变成了一段if-else
java·vue.js·spring boot·后端·ai编程
头茬韭菜2 小时前
4.1-4.2 工具注册 — Fail-Closed 类型安全设计与四层工具架构
java·安全·架构
SimonKing2 小时前
Base62编码生成6位不重复短码的背后设计
java·后端·程序员
折哥的程序人生 · 物流技术专研2 小时前
Java 23 种设计模式:从踩坑到精通 | 番外:状态 vs 策略 —— if-else 消除的两条路,你走对了吗?
java·spring·状态模式·策略模式·java面试·java设计模式·从踩坑到精通
等什么秋2 小时前
idea2024下载
java·ide·intellij-idea