设计模式——模板方法模式

模板方法模式 (Template Method Pattern)

什么是模板方法模式?

模板方法模式是一种行为型设计模式,它允许你在父类中定义一个算法的框架,而将一些步骤的实现延迟到子类中。

简单来说:模板方法模式就是"模板",父类定义框架,子类实现细节。

生活中的例子

想象一下:

  • 做菜:准备食材 → 烹饪 → 装盘(步骤相同,具体做法不同)
  • 考试:答题 → 交卷(步骤相同,具体内容不同)
  • 旅游:订票 → 出行 → 游玩 → 返回(步骤相同,具体安排不同)

为什么需要模板方法模式?

传统方式的问题

java 复制代码
// 每个子类都要重复定义框架
class A {
    public void doSomething() {
        step1();
        step2();
        step3();
    }
}

class B {
    public void doSomething() {
        step1();
        step2();
        step3();
    }
}

问题:

  1. 代码重复:框架代码重复
  2. 难以维护:修改框架需要修改多个类
  3. 不一致:框架可能不一致

模板方法模式的优势

java 复制代码
// 父类定义框架,子类实现细节
abstract class Template {
    public void doSomething() {
        step1();
        step2();
        step3();
    }
    
    protected abstract void step1();
    protected abstract void step2();
    protected abstract void step3();
}

优势:

  1. 代码复用:框架代码复用
  2. 易于维护:修改框架只需修改父类
  3. 一致性:框架保持一致
  4. 扩展容易:新增子类很容易

模板方法模式的结构

复制代码
┌─────────────────────┐
│  AbstractClass      │  抽象类
├─────────────────────┤
│ + templateMethod()  │
│   : void            │
│ # primitiveOp1():   │
│   void              │
│ # primitiveOp2():   │
│   void              │
│ # primitiveOp3():   │
│   void              │
└──────────┬──────────┘
           │ 继承
           ├──┬──────────────────┬──────────────┐
           │                    │              │
┌──────────┴──────┐  ┌───────────┴───────┐  ┌───┴────────┐
│ ConcreteClass1   │  │ ConcreteClass2    │  │ ...       │  具体类
├─────────────────┤  ├───────────────────┤  ├────────────┤
│ + primitiveOp1() │  │ + primitiveOp1()   │  │            │
│ + primitiveOp2() │  │ + primitiveOp2()   │  │            │
│ + primitiveOp3() │  │ + primitiveOp3()   │  │            │
└─────────────────┘  └───────────────────┘  └────────────┘

代码示例

1. 定义抽象类

java 复制代码
/**
 * 抽象类:做菜
 */
public abstract class CookDish {
    /**
     * 模板方法:定义做菜的流程
     */
    public final void cook() {
        prepareIngredients();
        cookDish();
        serveDish();
    }
    
    /**
     * 基本方法:准备食材
     */
    protected abstract void prepareIngredients();
    
    /**
     * 基本方法:做菜
     */
    protected abstract void cookDish();
    
    /**
     * 基本方法:上菜
     */
    protected abstract void serveDish();
}

2. 定义具体类

java 复制代码
/**
 * 具体类:做宫保鸡丁
 */
public class KungPaoChicken extends CookDish {
    @Override
    protected void prepareIngredients() {
        System.out.println("准备食材:鸡胸肉,花生米,干辣椒,花椒,葱,姜,蒜");
    }
    
    @Override
    protected void cookDish() {
        System.out.println("做菜步骤:");
        System.out.println("1. 鸡肉切丁,腌制");
        System.out.println("2. 花生米炸香盛起");
        System.out.println("3. 热锅下油,炒鸡丁");
        System.out.println("4. 加入干辣椒、花椒爆香");
        System.out.println("5. 调味,加入花生米翻炒");
    }
    
    @Override
    protected void serveDish() {
        System.out.println("上菜:宫保鸡丁做好了!");
    }
}

/**
 * 具体类:做西红柿炒鸡蛋
 */
public class TomatoEggs extends CookDish {
    @Override
    protected void prepareIngredients() {
        System.out.println("准备食材:西红柿2个,鸡蛋3个,葱,盐,糖");
    }
    
    @Override
    protected void cookDish() {
        System.out.println("做菜步骤:");
        System.out.println("1. 西红柿切块,鸡蛋打散");
        System.out.println("2. 热锅下油,炒鸡蛋盛起");
        System.out.println("3. 下西红柿炒出汁");
        System.out.println("4. 加入鸡蛋翻炒,调味");
    }
    
    @Override
    protected void serveDish() {
        System.out.println("上菜:西红柿炒鸡蛋做好了!");
    }
}

3. 使用模板方法

java 复制代码
/**
 * 模板方法模式测试类
 * 演示如何使用模板方法模式做菜
 */
public class TemplateMethodTest {
    
    public static void main(String[] args) {
        System.out.println("=== 模板方法模式测试 ===\n");
        
        // 做西红柿炒鸡蛋
        System.out.println("--- 做西红柿炒鸡蛋 ---");
        CookDish tomatoEggs = new TomatoEggs();
        tomatoEggs.cook();
        
        System.out.println("\n--- 做宫保鸡丁 ---");
        CookDish kungPaoChicken = new KungPaoChicken();
        kungPaoChicken.cook();
        
        System.out.println("\n=== 模板方法模式的优势 ===");
        System.out.println("1. 代码复用:框架代码复用");
        System.out.println("2. 易于维护:修改框架只需修改父类");
        System.out.println("3. 一致性:框架保持一致");
        System.out.println("4. 扩展容易:新增子类很容易");
        System.out.println("5. 控制扩展:父类控制扩展点");
        
        System.out.println("\n=== 实际应用场景 ===");
        System.out.println("1. Servlet:HttpServlet的doGet、doPost");
        System.out.println("2. JDBC:JDBC的执行流程");
        System.out.println("3. Spring:JdbcTemplate、RestTemplate");
        System.out.println("4. 生命周期:对象的生命周期管理");
        System.out.println("5. 算法框架:算法框架的实现");
        
        System.out.println("\n=== 钩子方法 ===");
        System.out.println("钩子方法是在模板方法中提供扩展点的方法:");
        System.out.println("- 可以在子类中覆盖");
        System.out.println("- 可以在模板方法中条件调用");
        System.out.println("- 提供更多的灵活性");
    }
}

模板方法模式的优点

  1. 代码复用:框架代码复用
  2. 易于维护:修改框架只需修改父类
  3. 一致性:框架保持一致
  4. 扩展容易:新增子类很容易
  5. 控制扩展:父类控制扩展点

模板方法模式的缺点

  1. 继承限制:只能通过继承扩展
  2. 类数量增加:每个实现都需要一个子类

适用场景

  1. 步骤固定:算法的步骤固定,但具体实现不同
  2. 代码复用:需要复用框架代码
  3. 控制扩展:需要控制扩展点

常见应用场景

  • Servlet:HttpServlet的doGet、doPost
  • JDBC:JDBC的执行流程
  • Spring:JdbcTemplate、RestTemplate

使用建议

  • 步骤固定:使用模板方法模式
  • 代码复用:使用模板方法模式
  • 步骤不固定:直接使用策略模式

注意事项

⚠️ 模板方法模式虽然有用,但要注意:

  • 不要让模板方法过于复杂
  • 考虑使用钩子方法
相关推荐
VidDown2 小时前
24fps 转 25fps 不只是改个数字:帧率转换、PAL/NTSC 与音频补偿
python·网络协议·音视频·视频编解码·视频
死磕音视频4 小时前
让小模型做选择题:限定候选项并读取 logits 概率的入门实践(附 Python 代码)
开发语言·python·大模型·文本分类·transformers
凤山老林4 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
pride.li6 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
databook6 小时前
用 Pydantic AI 从零搭建一个能干活的 AI Agent
人工智能·python
康小旺6 小时前
把 markitdown 做成 Windows 桌面版:拖进文档就出 Markdown,附 233MB→64MB 打包裁剪全过程
python
启观川7 小时前
数据结构与算法-第 3 章 常用算法-贪心算法
数据结构·笔记·python·算法·贪心算法
南笙北梦7 小时前
本地开源大模型多轮对话显存泄漏排查与修复实录
python
小羊没烦恼!7 小时前
如何在IIS6,7中部署ASP.NET网站?
数据库·后端·python·web安全·asp.net
钱栈up8 小时前
扫完 3.5 万文件后,我发现了 521 组散落的同名文件
爬虫·python·数据分析