模板方法模式

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

场景示例:茶(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() 是模板方法,它控制了制作饮料的整个流程,子类无法改变这个流程的结构,只能改变其中的部分实现。

优点

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

使用场景

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

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

相关推荐
.生产的驴18 分钟前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
猿周LV25 分钟前
JMeter 安装及使用 [软件测试工具]
java·测试工具·jmeter·单元测试·压力测试
晨集27 分钟前
Uni-App 多端电子合同开源项目介绍
java·spring boot·uni-app·电子合同
时间之城30 分钟前
笔记:记一次使用EasyExcel重写convertToExcelData方法无法读取@ExcelDictFormat注解的问题(已解决)
java·spring boot·笔记·spring·excel
椰羊~王小美37 分钟前
LeetCode -- Flora -- edit 2025-04-25
java·开发语言
凯酱44 分钟前
MyBatis-Plus分页插件的使用
java·tomcat·mybatis
程序员总部1 小时前
如何在IDEA中高效使用Test注解进行单元测试?
java·单元测试·intellij-idea
oioihoii1 小时前
C++23中if consteval / if not consteval (P1938R3) 详解
java·数据库·c++23
佳腾_1 小时前
【Web应用服务器_Tomcat】一、Tomcat基础与核心功能详解
java·前端·中间件·tomcat·web应用服务器
异常君2 小时前
线程池隐患解析:为何阿里巴巴拒绝 Executors
java·后端·代码规范