模版方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
- 模板方法定义了算法的步骤,把这些步骤的实现延迟到子类。
- 模板方法模式为我们提供了一种代码复用的重要技巧。
- 模板方法的抽象类可以定义具体方法、抽象方法和钩子。
- 抽象方法由子类实现。
- 钩子是一种方法,它在抽象类中不做事,或者只做默认的事情,子类可以选择要不要区覆盖它。
- 为了防止子类改变模板方法中的算法,可以将模板方法声明为final。
- 好莱坞原则告诉我们,将决策权放在高层模块中,以便决定如何以及何时调用低层模块。
- 你将在真实世界代码中看到模板方法模式的许多变体,不要期待他们全都是一眼就可以被你认出的。
- 策略模式和模板方法模式都封装算法,一个用组合一个用继承。
- 工厂方法是模板方法的一种特殊版本。
备注:
钩子:是一种被声明在抽象类中的方法,但只有空的或者默认的实现。
CaffeineBeverage:模版
public abstract class CaffeineBeverage { /** * 不希望子类覆盖这个方法,步骤2、4 泛化有子类去实现 */ final void prepareRecipe(){ boilWater(); brew(); pourInCup(); //默认是添加调料的,如果子类重写该方法就视情况而定了。 if (hook()){ addCondiments(); }else { System.out.println(".........不需要调料!"); } } abstract void brew(); abstract void addCondiments(); public void boilWater(){ System.out.println("...............烧水"); } public void pourInCup(){ System.out.println("............倒入杯子中"); } /** * 钩子,什么都不做,子类可以视情况决定要不要覆盖它们。 */ public boolean hook(){ return true; } }
public class Coffee extends CaffeineBeverage{ @Override public boolean hook(){ return false; } @Override void brew() { System.out.println(".......冲泡咖啡"); } @Override void addCondiments() { System.out.println(".......加奶和糖"); } }
public class Tea extends CaffeineBeverage{ @Override public void brew() { System.out.println("..........加入茶叶"); } @Override public void addCondiments() { System.out.println("..........加入柠檬"); } @Override public boolean hook(){ return true; } }
public class Test { public static void main(String[] args) { Coffee coffee = new Coffee(); Tea tea = new Tea(); tea.prepareRecipe(); System.out.println("--------------------------------"); coffee.prepareRecipe(); } }