模板方法模式

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

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

优点

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

使用场景

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

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

相关推荐
weixin_307779137 分钟前
AWS Elastic Beanstalk 实现 Java 应用高可用部署指南
java·开发语言·云计算·aws·web app
萝卜白菜。23 分钟前
关于Java EE应用中xml解析类的问题
xml·java·java-ee
一米阳光zw28 分钟前
Spring Boot中使用 MDC实现请求TraceId全链路透传
java·spring boot·后端·traceid·mdc
王元_SmallA42 分钟前
pgsql:connection failed connection to server at
java·后端
高山上有一只小老虎1 小时前
购物消费打折
java·算法
tuokuac1 小时前
@Configuration类中定义的@Bean方法
java
百锦再1 小时前
第8章 模块系统
android·java·开发语言·python·ai·rust·go
没有bug.的程序员1 小时前
Eureka 注册中心原理与服务注册发现机制
java·spring·云原生·eureka·架构·注册中心·服务注册发现
optimistic_chen1 小时前
【Java EE进阶 --- SpringBoot】统一功能处理
java·spring boot·java-ee·json·统一功能处理
西岭千秋雪_2 小时前
Zookeeper数据结构
java·数据结构·分布式·zookeeper