设计模式一一模版方法设计模式

62 阅读2分钟
  • 定义

    模板方法设计模式是一种行为型设计模式,它定义了算法的骨架(步骤顺序),允许子类在不改变算法结构的情况下重写某些步骤的具体实现。

  • 核心思想

    • 父类定义算法骨架(模板方法),包含步骤的调用顺序。
    • 子类实现具体步骤(如抽象方法或可覆盖方法),但不改变流程结构。
    • 关键:代码复用 + 扩展性(避免重复代码,同时允许灵活修改部分步骤)。

示例 :饮料制作(经典 GoF 例子)

// 抽象饮料类(定义模板方法)
abstract class Beverage {
    // 模板方法:final 防止子类修改流程
    public final void prepare() {
        boilWater();
        brew();
        pourInCup();
        if (customerWantsCondiments()) { // 钩子方法控制是否添加调料
            addCondiment();
        }
    }

    // 具体步骤:烧水(通用实现)
    private void boilWater() {
        System.out.println("1. 煮沸水");
    }

    // 抽象方法:冲泡(子类必须实现)
    protected abstract void brew();

    // 具体步骤:倒入杯子(通用实现)
    private void pourInCup() {
        System.out.println("3. 倒入杯子");
    }

    // 抽象方法:加调料(子类必须实现)
    protected abstract void addCondiment();

    // 钩子方法:默认加调料(子类可覆盖)
    protected boolean customerWantsCondiments() {
        return true;
    }
}

// 具体子类:咖啡
class Coffee extends Beverage {
    @Override
    protected void brew() {
        System.out.println("2. 冲泡咖啡粉");
    }

    @Override
    protected void addCondiment() {
        System.out.println("4. 加牛奶和糖");
    }

    // 覆盖钩子方法:假设顾客不要调料
    @Override
    protected boolean customerWantsCondiments() {
        return false;
    }
}

// 具体子类:茶
class Tea extends Beverage {
    @Override
    protected void brew() {
        System.out.println("2. 浸泡茶叶");
    }

    @Override
    protected void addCondiment() {
        System.out.println("4. 加柠檬");
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Beverage coffee = new Coffee();
        System.out.println("==== 制作咖啡 ====");
        coffee.prepare(); // 不会执行 addCondiment()

        Beverage tea = new Tea();
        System.out.println("\n==== 制作茶 ====");
        tea.prepare(); // 会执行 addCondiment()
    }
}

输出结果

==== 制作咖啡 ====
1. 煮沸水
2. 冲泡咖啡粉
3. 倒入杯子

==== 制作茶 ====
1. 煮沸水
2. 浸泡茶叶
3. 倒入杯子
4. 加柠檬

代码关键点解析

  1. 模板方法 (prepare())
    • 使用 final 修饰,确保子类无法修改饮料制作的步骤顺序。
    • 调用固定流程:boilWater() → brew() → pourInCup() → 条件调用 addCondiment()
  2. 通用步骤实现
    • boilWater()pourInCup() 是私有方法,直接复用父类逻辑,无需子类干预。
  3. 抽象方法
    • brew()addCondiment() 必须由子类实现,体现不同饮料的差异(如咖啡冲泡 vs 茶叶浸泡)。
  4. 钩子方法 (customerWantsCondiments())
    • 默认返回 true(允许加调料),但子类可覆盖(如 Coffee 类返回 false)。