模板方法模式

模板方法模式是一种行为设计模式,它定义了一个算法的骨架,将某些步骤延迟到子类中实现。通过模板方法,子类可以重定义算法的某些步骤,而不会改变算法的结构。

场景示例:茶(Tea)和咖啡(Coffee)的制作过程

制作茶和咖啡的过程有很多相似之处,但也有一些不同点。我们可以用模板方法模式来抽象出制作饮品的通用流程,并在子类中实现具体的操作。

制作茶和咖啡的步骤:

  1. 把水煮沸。
  2. 冲泡饮料(茶用茶叶,咖啡用咖啡粉)。
  3. 将饮料倒入杯子。
  4. 如果需要,可以添加配料(茶加柠檬,咖啡加糖和牛奶)。

代码实现:

1. 创建模板类 CaffeineBeverage

CaffeineBeverage 是一个抽象类,它包含了制作饮料的模板方法 prepareRecipe()。这个方法定义了制作饮品的骨架,而其中某些步骤由子类实现。

java 复制代码
public abstract class CaffeineBeverage {
    // 模板方法,定义了制作饮料的骨架
    public final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        if (customerWantsCondiments()) { // 钩子方法
            addCondiments();
        }
    }

    // 具体步骤:把水煮沸
    private void boilWater() {
        System.out.println("Boiling water");
    }

    // 具体步骤:将饮料倒入杯子
    private void pourInCup() {
        System.out.println("Pouring into cup");
    }

    // 抽象步骤:冲泡饮料
    protected abstract void brew();

    // 抽象步骤:添加配料
    protected abstract void addCondiments();

    // 钩子方法,子类可以覆盖此方法来改变算法的行为
    protected boolean customerWantsCondiments() {
        return true; // 默认添加配料
    }
}
2. 实现具体类 Tea

Tea 类继承自 CaffeineBeverage,并实现了冲泡和添加配料的具体逻辑。

java 复制代码
public class Tea extends CaffeineBeverage {
    @Override
    protected void brew() {
        System.out.println("Steeping the tea");
    }

    @Override
    protected void addCondiments() {
        System.out.println("Adding Lemon");
    }

    // 重写钩子方法,如果不需要配料
    @Override
    protected boolean customerWantsCondiments() {
        return false;  // 比如有时候顾客不想要加柠檬
    }
}
3. 实现具体类 Coffee

Coffee 类同样继承自 CaffeineBeverage,并实现了冲泡和添加配料的具体逻辑。

java 复制代码
public class Coffee extends CaffeineBeverage {
    @Override
    protected void brew() {
        System.out.println("Dripping coffee through filter");
    }

    @Override
    protected void addCondiments() {
        System.out.println("Adding Sugar and Milk");
    }
}
4. 测试客户端

在客户端中,我们可以通过调用 prepareRecipe() 方法来制作茶和咖啡。

java 复制代码
public class BeverageTest {
    public static void main(String[] args) {
        System.out.println("Making tea...");
        CaffeineBeverage tea = new Tea();
        tea.prepareRecipe();

        System.out.println("\nMaking coffee...");
        CaffeineBeverage coffee = new Coffee();
        coffee.prepareRecipe();
    }
}

输出结果

plaintext 复制代码
Making tea...
Boiling water
Steeping the tea
Pouring into cup

Making coffee...
Boiling water
Dripping coffee through filter
Pouring into cup
Adding Sugar and Milk

代码解释

  1. CaffeineBeverage :这个抽象类定义了制作饮料的模板方法 prepareRecipe(),这个方法包含制作饮品的通用步骤。brew()addCondiments() 是抽象方法,由具体的子类实现。

  2. TeaCoffee :这两个类继承自 CaffeineBeverage 并实现了冲泡和添加配料的具体逻辑。比如,Tea 中冲泡茶叶,Coffee 中使用滤器冲泡咖啡。

  3. 钩子方法customerWantsCondiments() 是一个可选的钩子方法,子类可以覆盖它来决定是否添加配料。比如,在 Tea 中,我们重写了该方法,返回 false,表示不需要配料。

  4. 模板方法prepareRecipe() 是模板方法,它控制了制作饮料的整个流程,子类无法改变这个流程的结构,只能改变其中的部分实现。

优点

  • 代码复用:公共的操作步骤在模板类中实现,避免代码重复。
  • 灵活性:通过钩子方法可以让子类决定是否执行某些步骤,而不会影响整体的算法结构。

使用场景

  • 适合具有统一流程结构、但某些步骤不同的场景。
  • 需要对算法步骤进行扩展或修改时,避免重复代码。

通过模板方法模式,可以灵活地定义算法的通用框架,并将部分实现留给子类完成,增加了代码的可扩展性和灵活性。

相关推荐
云动雨颤34 分钟前
Java并发性能优化|读写锁与互斥锁解析
java
ldj20201 小时前
Centos 安装Jenkins
java·linux
hqxstudying1 小时前
Intellij IDEA中Maven的使用
java·maven·intellij-idea
SimonKing1 小时前
拯救大文件上传:一文彻底彻底搞懂秒传、断点续传以及分片上传
java·后端·架构
深栈解码1 小时前
JUC并发编程 内存布局和对象头
java·后端
北方有星辰zz1 小时前
数据结构:栈
java·开发语言·数据结构
Seven971 小时前
一个static关键字引发的线上故障:深度剖析静态变量与配置热更新的陷阱
java
山野万里__1 小时前
C++与Java内存共享技术:跨平台与跨语言实现指南
android·java·c++·笔记
风象南1 小时前
Spring Shell命令行工具开发实战
java·spring boot·后端
Java技术小馆1 小时前
POST为什么发送两次请求
java·面试·架构