问题描述:

星巴克咖啡冲泡法:

1.净水煮沸;

2.用沸水冲泡咖啡

3.将咖啡倒入杯子

4.加奶和糖

冲泡茶方法:

1.净水煮沸;

2.用沸水冲泡茶

3.将茶倒入杯中

4.加柠檬

问题思路:

仔细观察我们可以得知,虽为两种饮料但制作过程相似。**我们可以将其抽象出一个父类,相同的步骤可在父类中定义,不同的步骤可在父类中定义为抽象类,在子类中具体实现(方法覆写),**这样的好处是程序冗余度较低,易修改(即若要新加子类只需要子类继承父类,再具体实现抽象方法即可,删除即只删除子类即可)。

源代码如下:

abstract class Drink{//抽象父类
    public void prepare(){
        boilWater();
        brew();
        dropIntoCup();
        add();
    }
    public void boilWater(){//净水煮沸与倒入杯中实则一样
        System.out.println("1.煮沸水");
    }
    public void dropIntoCup(){
        System.out.println("3.将饮料倒入杯中");
    }
    public abstract void brew();//抽象类
    public abstract void add();
}

class Coffee extends Drink{
    public void brew(){
        System.out.println("2.泡咖啡");
    }
    public void add(){
        System.out.println("4.加牛奶或糖");
    }
}

class Tea extends Drink{
    public void brew(){//父类中的抽象类在子类中具体实现
        System.out.println("2.泡茶");
    }
    public void add(){
        System.out.println("4.加柠檬");
    }
}

public class Test{
    public static void main(String[] args){
        Drink drink1=new Coffee();//抽象类不可直接实例化对象,但可通过子类向上转型访问父类成员
        drink1.prepare();//实例化对象调用prepare方法
        Drink drink2=new Tea();
        drink2.prepare();
    }
}

源程序类图为:

模板方法模式---星巴克泡茶泡咖啡例题

程序运行结果:**

模板方法模式---星巴克泡茶泡咖啡例题

源程序演变过程:

//将Coffee类与Tea类独立开来
class Coffee{
    public void prepare(){
        boilWater();
        brewCoffee();
        dropCoffeeIntoCup();
        addSugerAndMilk();
    }
    public void boilWater(){
        System.out.println("1.用开水煮");
    }
    public void brewCoffee(){
        System.out.println("2.泡咖啡");
    }
    public void dropCoffeeIntoCup(){
        System.out.println("3.倒咖啡");
    }
    public void addSugerAndMilk(){
        System.out.println("4.加牛奶或糖");
    }
}

class Tea{
    public void prepare(){
        boilWater();
        brewTea();
        dropTeaIntoCup();
        addLemon();
    }
    public void boilWater(){
        System.out.println("1.开水煮");
    }
    public void brewTea(){
        System.out.println("2.泡茶");
    }
    public void dropTeaIntoCup(){
        System.out.println("3.将茶倒入杯中");
    }
    public void addLemon(){
        System.out.println("4.加柠檬");
    }
}
public class Test{
    public static void main(String[] args){
        Coffee coffee=new Coffee();
        coffee.prepare();
        Tea tea=new Tea();
        tea.prepare();
    }
}

此代码类图为:

模板方法模式---星巴克泡茶泡咖啡例题

此代码优点是通俗易懂,但代码冗余度高,不利于覆写。

//抽象出父类,将相同的操作放置与父类实现,子类继承即可
class Drink{
    public void prepare(){
        boilWater();
        dropIntoCup();
    }
    public void boilWater(){
        System.out.println("1.煮沸水");
    }
    public void dropIntoCup(){
        System.out.println("3.将饮料倒入杯中");
    }
}
class Coffee extends Drink{
    public void prepare(){
        boilWater();
        brewCoffee();
        dropIntoCup();
        addSugerAndMilk();
    }
    public void brewCoffee(){
        System.out.println("2.泡咖啡");
    }
    public void addSugerAndMilk(){
        System.out.println("4.加牛奶或糖");
    }
}

class Tea extends Drink{
    public void prepare(){
        boilWater();
        brewTea();
        dropIntoCup();
        addLemon();
    }
    public void brewTea(){
        System.out.println("2.泡茶");
    }
    public void addLemon(){
        System.out.println("4.加柠檬");
    }
}
public class Test{
    public static void main(String[] args){
        Coffee coffee=new Coffee();
        coffee.prepare();
        Tea tea=new Tea();
        tea.prepare();
    }
}

此程序类图为:

模板方法模式---星巴克泡茶泡咖啡例题

此程序相较于之前程序逻辑性加强,但任然冗余度高。于是利用抽象类与抽象方法书写时,就使得子类在不改变算法结构的情况下,重新定义算法中的某些步骤(子类具体实现抽象方法)。

相关文章: