public abstract class CaffeineBeverage { // 现在,用同一个prepareRecipe()方法来处理茶和咖啡。 // prepareRecipe()方法被声明为final,因为我们不希望子类覆盖这个方法 // 我们将第2步和第4步泛化成为brew()和addCondiments() final void prepareRecipe() { boilWater();//烧水 brew();//冲泡 pourInCup();//倒入杯中 addCondiments();//加入调料 } // 因为咖啡和茶处理这些方法的做法不同,所以这两个方法必须被声明为抽象, // 剩余的东西留给子类去操心 abstract void addCondiments(); abstract void brew(); public void boilWater() {//冲咖啡和泡茶的这个方法相同 System.out.println("Boiling water"); } public void pourInCup() { System.out.println("Pouring into cup"); } }3、定义咖啡和茶的具体流程实现,这两个类现在都是依赖超类来处理冲泡法,所以只需要自行处理冲泡和添加调料部分
public class Coffee extends CaffeineBeverage { @Override void brew() { System.out.println("Dripping coffee through filter"); } @Override void addCondiments() { System.out.println("Adding Sugar and Milk"); } } public class Tea extends CaffeineBeverage { @Override void brew() { System.out.println("Steeping the tea"); } @Override void addCondiments() { System.out.println("Adding Lemon"); } }4、编写测试类
public class Test { public static void main(String[] args) { //冲咖啡 Coffee coffee=new Conffee(); coffee.prepareRecipe(); System.out.println("冲咖啡完毕"); //泡茶 Tea tea = new Tea(); tea.prepareRecipe(); System.out.println("泡茶完毕"); } }测试结果:
Boiling water Dripping coffee through filter Pouring into cup Adding Sugar and Milk 冲咖啡完毕 Boiling water Steeping the tea Pouring into cup Adding Lemon 泡茶完毕
三、对模板方法进行挂钩
如果某些客户并不喜欢加入调料,而喜欢原生态的,但是我们的算法总是会给客户加入调料,怎么解决?public abstract class CaffeineBeverageWithHook { final void prepareRecipe() { boilWater(); brew(); pourInCup(); // 我们加上了一个小小的条件语句,而该条件是否成立, // 是由一个具体方法customerWantsCondiments()决定的。 // 如果顾客“想要”调料,只有这时我们才调用addCondiments()。 if (customerWantsCondiments()) { addCondiments(); } } abstract void addCondiments(); abstract void brew(); public void boilWater() { System.out.println("Boiling water"); } public void pourInCup() { System.out.println("Pouring into cup"); } // 我们在这里定义了一个方法,(通常)是空的缺省实现。这个方法只会返回true,不做别的事。 // 这就是一个钩子,子类可以覆盖这个方法,但不见得一定要这么做。 boolean customerWantsCondiments() { return true; } }2、泡咖啡的流程实现
public class Coffee extends CaffeineBeverageWithHook { public boolean isAddCondiments=true;//默认加入调料 @Override void brew() { System.out.println("Dripping coffee through filter"); } @Override void addCondiments() { System.out.println("Adding Sugar and Milk"); } boolean customerWantsCondiments() { return isAddCondiments; } public void setIsAddCondiments(boolean isAddCondiments){ this.isAddCondiments=isAddCondiments; } }泡茶的实现与之类似,这里不做详述。