模板方法模式

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

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

优点

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

使用场景

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

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

相关推荐
0x5319 分钟前
JAVA|智能无人机平台(二)
java·开发语言·无人机
JH307327 分钟前
SpringBoot自定义启动banner:给项目加个专属“开机画面”
java·spring boot·后端
假女吖☌42 分钟前
限流算法-redis实现与java实现
java·redis·算法
lixin5565561 小时前
基于迁移学习的图像风格增强器
java·人工智能·pytorch·python·深度学习·语言模型
面汤放盐1 小时前
企业权限--系统性方案探究
java·开发语言
what丶k1 小时前
深度解析Redis LRU与LFU算法:区别、实现与选型
java·redis·后端·缓存
悟能不能悟1 小时前
java Date转换为string
java·开发语言
菜宾1 小时前
java-redis面试题
java·开发语言·redis
猿小羽1 小时前
AI 学习与实战系列:Spring AI + MCP 深度实战——构建标准化、可扩展的智能 Agent 系统
java·spring boot·llm·agent·spring ai·mcp·model context protocol
木井巳1 小时前
【递归算法】快速幂解决 pow(x,n)
java·算法·leetcode·深度优先