1、概述
模板模式:封装了一个算法步骤(prepareRecipe),并允许子类为一个或多个步骤方法提供实现模板模式可以使子类在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板是一个抽象类,模板中所包含的内容:
- 1、算法步骤,使用final修饰,子类不可更改
- 2、已经实现的方法,使用final修饰,子类不可更改
- 3、抽象的方法
- 4、hook,子类可选项
如泡茶喝泡咖啡,总共有以下四个步骤:
- 1、烧开水
- 2、冲泡
- 3、倒入杯子中
- 4、添加佐料
所以我们将这四个步骤定义成一个模板,具体代码如下:
public abstract class HotDrink { // 封装了算法步骤,使用final修饰,表示子类不能更改算法步骤 public final void prepareRecipe() { boilWater(); brew(); pourInCup(); addCondiments(); } public abstract void boilWater(); public abstract void brew(); public abstract void pourInCup(); public abstract void addCondiments(); }
由于泡茶和泡咖啡的第一步和第三步操作是相同的,所以我们可以对父类模板作进一步的优化:
public abstract class HotDrink { public final void prepareRecipe() { boilWater(); brew(); pourInCup(); addCondiments(); } // 已经实现的方法 public final void boilWater() { System.out.println("Boiling water"); } // 抽象方法 public abstract void brew(); public final void pourInCup() { System.out.println("Pouring into cup"); } public abstract void addCondiments(); }
泡茶类实现如下:
public class Tea extends HotDrink{ @Override public void brew() { System.out.println("Brewing tea"); } @Override public void addCondiments() { System.out.println("Adding lemon"); } }
泡咖啡类实现如下:
public class Coffee extends HotDrink{ @Override public void brew() { System.out.println("Brewing Coffee "); } @Override public void addCondiments() { System.out.println("Adding sugar and milk"); } }
运行类实现如下:
public class MainTest { public static void main(String[] args) { HotDrink mCoffee = new Coffee() ; HotDrink tea = new HotDrink(); mCoffee.prepareRecipe(); tea.prepareRecipe(); } }
2、模板模式中的hook
虽然超类的算法步骤是final的,但是子类可以通过覆盖hook函数的方法来影响超类的算法步骤
hook为子类覆盖方法的可选项,父类默认实现,子类可进行覆盖后更改
如泡茶和泡咖啡中的第四步,假如我们将模板定义为第四步是可以选项,则我们可以将模板代码定义成如下:
public abstract class HotDrinkTemplate { public final void prepareRecipe() { boilWater(); brew(); pourInCup(); // 默认为加佐料 if(wantCondimentsHook()){ addCondiments(); }else{ System.out.println("No Condiments"); } } // hook方法默认实现,子类可覆盖 public boolean wantCondimentsHook() { return true; } public final void boilWater() { System.out.println("Boiling water"); } public abstract void brew(); public final void pourInCup() { System.out.println("Pouring into cup"); } public abstract void addCondiments(); }
子类可实现如下:
public class TeaWithHook extends HotDrinkTemplate{ @Override public void brew() { System.out.println("Brewing tea"); } @Override public void addCondiments() { System.out.println("Adding lemon"); } @Override public boolean wantCondimentsHook() { return false; } }