Java-----模板设计模式

模板设计模式是基于抽象类的,它的核心是封装算法
我们可以先用代码实现泡茶和冲咖啡的过程:
泡茶的步骤:

  1. 将水煮沸
  2. 用沸水浸泡茶叶
  3. 把茶倒进杯子
  4. 加柠檬

冲咖啡的步骤:
5. 将水煮沸
6. 用沸水冲泡咖啡
7. 将咖啡倒进杯子
8. 加糖和牛奶
代码实现:

package www.java.test;

class Coffe{
    //咖啡的冲泡方法
    void prepareRecipe(){
        boilWater();
        brewCoffee();
        pourInCup();
        addSugarAndMilk();
    }
    void boilWater(){
        System.out.println("将水烧开");
    }
    void brewCoffee(){
        System.out.println("冲泡咖啡");
    }
    void pourInCup(){
        System.out.println("将咖啡倒入杯子");
    }
    void addSugarAndMilk(){
        System.out.println("加糖和牛奶");
    }
}

class Tea{
    void prepareRecipe(){
        boilWater();
        steepTeaBag();
        pourInCup();
        addLemon();
    }
    void boilWater(){
        System.out.println("将水烧开");
    }
    void steepTeaBag(){
        System.out.println("浸泡茶叶");
    }
    void pourInCup(){
        System.out.println("将茶倒入杯中");
    }
    void addLemon(){
        System.out.println("加柠檬");
    }
}

public class Test{
    public static void main(String[] args) {
        Coffe coffe = new Coffe();
        Tea tea = new Tea();
        coffe.prepareRecipe();
        tea.prepareRecipe();
    }
}

在这里插入图片描述
但是我们会发现虽然实现了功能,但是有大量的重复代码,这个问题如何解决呢?
我们可以把它们共同的部分抽取出来,放进一个基类中。
它们的共同点:

  1. 它们的boilWater()和pourInCup()这两个方法是有共同点的
  2. 这两种泡法的算法也都是一样的,我们也可以将prepareRecipe()抽象化这两种泡法的算法也都是一样的,我们也可prepareRecipe()抽象化
  3. 实际上浸泡(steep)和冲泡(brew)差异并不大,所以我们可以给它起一个新的名字brew(),无论是加哪种饮料都可以使用这个方法
  4. 加糖、牛奶还是柠檬也很相似,都是在加调料,所以也给它起一个共同的名字addCondiments()。

要想让某些方法延迟到子类实现,就需要用到抽象类和抽象方法。
我们再来看看修改后的代码:

package www.java.test;

abstract class CaffeineBeverage{
    //只允许子类使用,不允许被覆写,不准子类修改核心冲泡法
    //模板方法
     final void prepareRecipe(){
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }
    void boilWater(){
        System.out.println("将水烧开");
    }
    void pourInCup(){
        System.out.println("将饮料倒入杯中");
    }
    abstract void brew();
    abstract void addCondiments();
}
class Coffee extends CaffeineBeverage{
    void brew(){
        System.out.println("冲泡咖啡");
    }
    void addCondiments(){
        System.out.println("加糖和牛奶");
    }
}
class Tea extends CaffeineBeverage{

    @Override
    void brew() {
        System.out.println("浸泡茶叶");
    }

    @Override
    void addCondiments() {
        System.out.println("加柠檬");
    }
}
public class Test{
    public static void main(String[] args) {
        CaffeineBeverage coffee = new Coffee();
        CaffeineBeverage tea = new Tea();
        coffee.prepareRecipe();
        coffee.prepareRecipe();
    }
}

在这里插入图片描述
这样给我们带来的好处就是:

  1. 代码复用最大化。
  2. 有利于扩展(加入现在如果来一个新的饮料,那如果没有抽象它的一些方法,那我们就需要把整个流程的算法都重写一遍,这样很麻烦,如果用来模板方法,我们只需要实现自己的冲泡和加料方法)

模板方法定义了一个算法的步骤,并允许子类为一个或多个步骤提供具体实现。

模板模式:就是在一个方法中定义一个算法的骨架,并将一些具体的实现步骤延迟到子类实现,可以使得子类在不改变算法结构的前提下,重新具体定义算法中的某些步骤。

假如我们现在想喝黑咖啡,不想加糖或牛奶,我们如何做呢?
我们可以给这个模板方法加一个钩子方法,在子类中可以选择性的覆写它,比如只需要在咖啡中覆写它。

package www.java.test;

import java.util.Scanner;

abstract class CaffeineBeverage{
    //只允许子类使用,不允许被覆写,不准子类修改核心冲泡法
     final void prepareRecipe(){
        boilWater();
        brew();
        pourInCup();
        if(customerWantsCondiments()) {
            addCondiments();
        }
    }
    void boilWater(){
        System.out.println("将水烧开");
    }
    void pourInCup(){
        System.out.println("将饮料倒入杯中");
    }
    //钩子方法
    boolean customerWantsCondiments(){
         return true;
    }
    abstract void brew();
    abstract void addCondiments();
}
class Coffee extends CaffeineBeverage{
    void brew(){
        System.out.println("冲泡咖啡");
    }
    void addCondiments(){
        System.out.println("加糖和牛奶");
    }
    boolean customerWantsCondiments(){
        System.out.println("你需要加糖或牛奶吗? y/n");
        String result = getUserInfo();
        if(result.equals("y")){
            return true;
        }else{
            return false;
        }
    }
    //获取用户的输入
    private String getUserInfo(){
        Scanner scanner = new Scanner(System.in);
        String str = scanner.nextLine();
        return str;
    }
}
class Tea extends CaffeineBeverage{

    @Override
    void brew() {
        System.out.println("浸泡茶叶");
    }

    @Override
    void addCondiments() {
        System.out.println("加柠檬");
    }
}
public class Test{
    public static void main(String[] args) {
        CaffeineBeverage coffee = new Coffee();
        CaffeineBeverage tea = new Tea();
        coffee.prepareRecipe();
        tea.prepareRecipe();
    }
}

猜你喜欢

转载自blog.csdn.net/huaijiu123/article/details/86484486