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

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

使用建议

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

注意事项

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

  • 不要让模板方法过于复杂
  • 考虑使用钩子方法
相关推荐
寻星探路2 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
ValhallaCoder5 小时前
hot100-二叉树I
数据结构·python·算法·二叉树
猫头虎6 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
八零后琐话6 小时前
干货:程序员必备性能分析工具——Arthas火焰图
开发语言·python
书院门前细致的苹果7 小时前
设计模式大全:单例、工厂模式、策略模式、责任链模式
设计模式·责任链模式·策略模式
青春不朽5127 小时前
Scrapy框架入门指南
python·scrapy
MZ_ZXD0018 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
全栈老石8 小时前
Python 异步生存手册:给被 JS async/await 宠坏的全栈工程师
后端·python
梨落秋霜8 小时前
Python入门篇【模块/包】
python