设计模式之模板模式引导篇

  • 作者: 凯哥Java(公众号:凯哥Java)
  • 设计模式
  • 时间:2019-09-05 07:16
  • 5401人已阅读
简介 在讲模板模式原理前,我们按照惯例,先来个生活中例子。茶馆需要开发一个自动的泡咖啡和泡茶的程序。来源:凯哥Java(kaigejava)我们先来看看泡咖啡和泡茶的步骤:我们根据上图写代码实现:泡咖啡类,如下图:泡茶类如下图:测试类:运行结果:很简单。也很容易写出来。写出来很清楚。从上图中,可以发现,两个流程几乎是一样的套路(步骤)。其中,不变的部分:水烧开、倒入杯子、送给客人。这三步是不变的。变化的

🔔🔔好消息!好消息!🔔🔔

 如果您需要注册ChatGPT,想要升级ChatGPT4。凯哥可以代注册ChatGPT账号代升级ChatGPT4

有需要的朋友👉:微信号 kaigejava2022


设计模式之模板模式引导篇



在讲模板模式原理前,我们按照惯例,先来个生活中例子。茶馆需要开发一个自动的泡咖啡和泡茶的程序。

来源:凯哥Java(kaigejava)

我们先来看看泡咖啡和泡茶的步骤:

设计模式之模板模式引导篇


我们根据上图写代码实现:

泡咖啡类,如下图:

设计模式之模板模式引导篇


泡茶类如下图:

设计模式之模板模式引导篇


测试类:

设计模式之模板模式引导篇


运行结果:

设计模式之模板模式引导篇


很简单。也很容易写出来。写出来很清楚。

从上图中,可以发现,两个流程几乎是一样的套路(步骤)。其中,不变的部分:水烧开、倒入杯子、送给客人。这三步是不变的。

变化的是:冲咖啡还是泡茶叶;加糖/牛奶还是加柠檬这两个步骤是变化的。

项目进化第一个版本:

我们将不变的抽取出来,放到一个公共的类中。HotDrink。然后让coffe和tea都继承公共的类。得到的类图如下:

设计模式之模板模式引导篇


hotdrink超类代码如下:

设计模式之模板模式引导篇


项目进化第二个版本:

经过分析,我们发现,两个流程的还有相同的地方:

1.两个流程的步骤都一样(都是五个步骤的);

2.无论泡茶还是泡咖啡都是brew操作;

3.无论加糖还是加柠檬都是添加调料的。

所以,我们对项目在进行一次提取:

我们将操作流程也提取到超类中,将2和3操作也放到超类中。让子类具体实现。所以得到类图如下:

设计模式之模板模式引导篇


我们来看看这次hotdrink类里面:

public abstract class HotDrink {

public final void prepareRecipe(){

boilWater();

brew();

pourInCup();

addCondiments();

send();

}

protected abstract void addCondiments();

protected abstract void brew();

private final void boilWater() {

System.out.println("一.烧水");

}

private final void pourInCup() {

System.out.println("三.倒入杯中");

}

设计模式之模板模式引导篇


我们发现,在prepareRecipe方法和boilWter、pourInCup、send这四个操作都添加了final关键字来修改。这是为什么呢?

从上面分析,我们知道,都是五个步骤,而且五个步骤中的三个步骤(烧水、倒入杯中、送客人)也是固定不变的。那么,在Java中,固定不变的这个怎么表示呢?对了,就使用fianl这个关键字修饰就可以了。这样,就可以放置子类不能随便修改步骤(比如由五步变成三步),已经规定的不能在修改了。比如烧水这个不烧了,这样是不行的。

我们来看看,热饮coffee和tea的类:

设计模式之模板模式引导篇


hotDrinkTea:

设计模式之模板模式引导篇


测试方法:

设计模式之模板模式引导篇


运行结果:

设计模式之模板模式引导篇


我们对项目进化进行复盘总结,可以得到:

所谓的模板模式:封装了一个算法的步骤,并允许子类为一个或多个步骤方法提供实现。模板模式,可以使子类在不改变算法结构(如上面的五步)的情况下,重新定义算法中某些步骤(如上面的第二步和第四步)

模板模式类图如下:

设计模式之模板模式引导篇


类图说明:

1:是一个抽象类(如:hotDrink)

2:有个模板方法。这个模板方法是final的(如:prepareRecipe方法)

3:由三种方法:

AbsOperation:抽象的方法(泡咖啡、加牛奶)

concreteOp:具体的方法(如烧水。可以是final的也可以不是)

hook:钩子。可以选的子类可以覆盖父类的方法。

我们来演示下带有hook的。

比如,现在有了新需求,客户可以自己选择需不需要添加调料。这个怎么做呢?

我们从新定义模板:

设计模式之模板模式引导篇


tea实现了该模板类,并且不加柠檬的:

设计模式之模板模式引导篇


测试运行:

设计模式之模板模式引导篇


结果:

设计模式之模板模式引导篇


TopTop