Java 编程之模板方法模式

发布于:2025-07-04 ⋅ 阅读:(19) ⋅ 点赞:(0)

引言

本文用一杯茶咖,让你喝懂模板方法模式设计思想

☕ “程序员不止写代码,也懂泡茶和冲咖啡。”
模板方法模式——把固定的流程封装在抽象类中,把可变的步骤交给子类决定。本文通过生活化例子+代码一一对应讲透它!


一、模板方法模式定义

模板方法模式(Template Method Pattern)是一种行为型设计模式,用于定义一个操作中的算法骨架,而将一些步骤的实现延迟到子类中

通俗地说:

父类定流程,子类补细节。

这使得子类在不改变整体算法结构的前提下,能够重新定义某些步骤的实现方式


二、类比用例

在生活中,泡茶与冲咖啡为例来理解这一设计模式。

泡茶与冲咖啡的流程都很像:

  1. 烧开水
  2. 冲泡
  3. 倒入杯中
  4. 如果愿意,可以加入佐料(如柠檬片、糖、牛奶等)

于是,我们可以把这套流程抽象为一个“饮品冲泡模板”,具体细节(茶叶 or 咖啡粉,是否加佐料)由子类决定。


三、模板方法模式结构

在这里插入图片描述

@startuml
abstract class CaffeineBeverage {
    +prepareRecipe()
    -boilWater()
    -pourInCup()
    +brew() : abstract
    +addCondiments() : abstract
}

class Tea extends CaffeineBeverage
class Coffee extends CaffeineBeverage

CaffeineBeverage <|-- Tea
CaffeineBeverage <|-- Coffee
@enduml

四、代码实现:把生活变代码

4.1. 饮品冲泡模板(抽象类)

public abstract class CaffeineBeverage {

    // 模板方法,不可重写
    public final void prepareRecipe() {
        boilWater();
        brew();                 // 由子类实现
        pourInCup();
        if (customerWantsCondiments()) {
            addCondiments();    // 由子类实现
        }
    }

    void boilWater() {
        System.out.println("把水煮沸");
    }

    void pourInCup() {
        System.out.println("把饮料倒进杯子");
    }

    // 钩子方法:子类可以选择是否重写
    boolean customerWantsCondiments() {
        return true;
    }

    abstract void brew();           // 冲泡方式不同
    abstract void addCondiments();  // 添加佐料方式不同
}

4.2. 茶类实现

public class Tea extends CaffeineBeverage {

    @Override
    void brew() {
        System.out.println("用热水浸泡茶叶");
    }

    @Override
    void addCondiments() {
        System.out.println("加点柠檬片");
    }

    @Override
    boolean customerWantsCondiments() {
        return true; // 或根据用户输入来动态判断
    }
}

4.3. 咖啡类实现

public class Coffee extends CaffeineBeverage {

    @Override
    void brew() {
        System.out.println("用热水冲泡咖啡粉");
    }

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

    @Override
    boolean customerWantsCondiments() {
        return false; // 咖啡师决定不加
    }
}

4.4. 客户端享用

public class BeverageTestDrive {
    public static void main(String[] args) {
        System.out.println("---------- 泡一杯茶 ----------");
        CaffeineBeverage tea = new Tea();
        tea.prepareRecipe();

        System.out.println("\n---------- 冲一杯咖啡 ----------");
        CaffeineBeverage coffee = new Coffee();
        coffee.prepareRecipe();
    }
}

输出结果:

---------- 泡一杯茶 ----------
把水煮沸
用热水浸泡茶叶
把饮料倒进杯子
加点柠檬片

---------- 冲一杯咖啡 ----------
把水煮沸
用热水冲泡咖啡粉
把饮料倒进杯子

五、关键点分析

步骤 属于抽象类 属于子类 是否可扩展
boilWater()
brew()
addCondiments()
prepareRecipe() ✅(final)
customerWantsCondiments() ✅(钩子) ✅(可重写) ✅(灵活)

六、优缺点总结

模板方法模式:
流程写死在抽象类,把差异开放给子类
这样就能稳定结构,又自由扩展

优点

  • 提高代码复用性:公共流程只写一次,子类只专注差异化实现。
  • 提高扩展性:子类可按需定制部分步骤。
  • 实现**“开闭原则”**:结构稳定,细节可变。

缺点

  • 增加了类的数量(每种实现都要新建类)
  • 对类结构理解有一定要求,不适合流程极度不确定的场景

七、应用场景

模板方法常见于以下场景:

  • 框架设计:如 Servlet 的 doGet() / doPost()service() 中被调用。
  • 数据处理流程:读取文件 → 解析 → 验证 → 存储。
  • 游戏或AI算法中的行为模板。

八、附加建议:代码增强思路

  • 增加用户交互 Scanner 控制是否加佐料
  • Logger 代替 System.out.println
  • 封装为“饮品工厂”模式组合使用

九、参考

《23种设计模式概览》
在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到