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

模板方法模式 (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

使用建议

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

注意事项

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

  • 不要让模板方法过于复杂
  • 考虑使用钩子方法
相关推荐
The_cute_cat1 小时前
关于PyCharm使用Poetry的避坑
ide·python·pycharm
UR的出不克2 小时前
【Python实战】基于Flask+TensorFlow的网易云音乐数据分析系统:从数据爬取到情感分析的全流程实现
python·flask·tensorflow
涅小槃2 小时前
Carla仿真学习笔记(版本0.9.16)
开发语言·python·ros·carla
witAI2 小时前
2025动漫剧本创作工具推荐,助力逆袭重生动态漫
python·量子计算
wujialaoer2 小时前
常用软件阿里源地址
开发语言·python
Ro Jace2 小时前
A Real-Time Cross Correlator for Neurophysiological Research
人工智能·python·算法
还不秃顶的计科生2 小时前
查看linux服务器中某文件夹占用空间大小
服务器·python
T_Fire_of_Square2 小时前
crewai的进一步工具扩展
python·github
喵手2 小时前
Python爬虫零基础入门【第三章:Requests 静态爬取入门·第3节】稳定性第一课:超时、重试、退避(指数退避)!
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·requests静态爬取·超时、重试、退避