23种设计模式23种设计模式
首页
介绍
  • 单例模式
  • 工厂方法模式
  • 抽象工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 桥接模式
  • 组合模式
  • 装饰器模式
  • 外观模式
  • 享元模式
  • 代理模式
  • 责任链模式
  • 命令模式
  • 解释器模式
  • 迭代器模式
  • 中介者模式
  • 备忘录模式
  • 观察者模式
  • 状态模式
  • 策略模式
  • 模板方法模式
  • 访问者模式
🚀 编程指南
首页
介绍
  • 单例模式
  • 工厂方法模式
  • 抽象工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 桥接模式
  • 组合模式
  • 装饰器模式
  • 外观模式
  • 享元模式
  • 代理模式
  • 责任链模式
  • 命令模式
  • 解释器模式
  • 迭代器模式
  • 中介者模式
  • 备忘录模式
  • 观察者模式
  • 状态模式
  • 策略模式
  • 模板方法模式
  • 访问者模式
🚀 编程指南
  • 行为型模式

    • 责任链模式 (Chain of Responsibility)
    • 命令模式 (Command)
    • 解释器模式 (Interpreter)
    • 迭代器模式 (Iterator)
    • 中介者模式 (Mediator)
    • 备忘录模式 (Memento)
    • 观察者模式 (Observer)
    • 状态模式 (State)
    • 策略模式 (Strategy)
    • 模板方法模式 (Template Method)
    • 访问者模式 (Visitor)

模板方法模式 (Template Method)

📖 通俗理解

做菜的标准流程:

  1. 准备食材
  2. 放油热锅
  3. 放入食材(不同菜不同)
  4. 调味(不同菜不同)
  5. 出锅装盘

流程是固定的,但具体某些步骤因菜而异。

模板方法模式就是:定义一个操作的算法骨架,将某些步骤延迟到子类中实现。

🎯 解决什么问题?

多个类有相似的流程,只是某些步骤不同。把相同的部分提取到父类,不同的部分由子类实现。

🌰 生活中的例子

  • 做菜流程:备菜 → 炒菜 → 出锅
  • 考试流程:发卷 → 答题 → 收卷
  • 面试流程:自我介绍 → 技术面 → HR 面

💻 Java 代码实现

场景:饮料制作

/**
 * 抽象类:饮料模板
 */
public abstract class Beverage {
    
    // 模板方法(final 防止子类修改流程)
    public final void prepare() {
        boilWater();
        brew();           // 抽象方法,子类实现
        pourInCup();
        if (needCondiments()) {  // 钩子方法
            addCondiments();
        }
    }
    
    private void boilWater() {
        System.out.println("1. 烧开水");
    }
    
    // 抽象方法:冲泡
    protected abstract void brew();
    
    private void pourInCup() {
        System.out.println("3. 倒入杯中");
    }
    
    // 抽象方法:加配料
    protected abstract void addCondiments();
    
    // 钩子方法:是否需要配料(子类可覆盖)
    protected boolean needCondiments() {
        return true;
    }
}

/**
 * 茶
 */
public class Tea extends Beverage {
    
    @Override
    protected void brew() {
        System.out.println("2. 冲泡茶叶");
    }
    
    @Override
    protected void addCondiments() {
        System.out.println("4. 加柠檬");
    }
}

/**
 * 咖啡
 */
public class Coffee extends Beverage {
    
    @Override
    protected void brew() {
        System.out.println("2. 冲泡咖啡");
    }
    
    @Override
    protected void addCondiments() {
        System.out.println("4. 加糖和牛奶");
    }
}

/**
 * 纯净水(不需要配料)
 */
public class PureWater extends Beverage {
    
    @Override
    protected void brew() {
        System.out.println("2. 直接用矿泉水");
    }
    
    @Override
    protected void addCondiments() {
        // 不需要
    }
    
    @Override
    protected boolean needCondiments() {
        return false;  // 覆盖钩子方法
    }
}

使用:

public class Client {
    public static void main(String[] args) {
        System.out.println("=== 制作茶 ===");
        Beverage tea = new Tea();
        tea.prepare();
        
        System.out.println("\n=== 制作咖啡 ===");
        Beverage coffee = new Coffee();
        coffee.prepare();
        
        System.out.println("\n=== 纯净水 ===");
        Beverage water = new PureWater();
        water.prepare();
    }
}

输出:

=== 制作茶 ===
1. 烧开水
2. 冲泡茶叶
3. 倒入杯中
4. 加柠檬

=== 制作咖啡 ===
1. 烧开水
2. 冲泡咖啡
3. 倒入杯中
4. 加糖和牛奶

=== 纯净水 ===
1. 烧开水
2. 直接用矿泉水
3. 倒入杯中

🔥 钩子方法

钩子方法(Hook):父类提供默认实现,子类可以选择性覆盖来影响流程。

// 钩子方法示例
protected boolean needCondiments() {
    return true;  // 默认需要配料
}

✅ 适用场景

  1. 多个类有相同的算法结构
  2. 需要控制子类扩展的点
  3. 提取公共代码,避免重复

📚 框架中的应用

  • Spring:JdbcTemplate
  • Servlet:HttpServlet 的 service() 方法
  • JUnit:setUp() 和 tearDown()

小结

模板方法模式:定义算法骨架,具体步骤由子类实现。

关键点:

  • 模板方法定义流程(用 final 修饰)
  • 抽象方法由子类实现
  • 钩子方法让子类可选择性影响流程

👉 下一篇:访问者模式

Prev
策略模式 (Strategy)
Next
访问者模式 (Visitor)