1.为什么使用模板
定义一个算法框架,将框架内方法延迟到子类去实现,这样可以在不改变算法整体流程的情况下,重新定义某些细节。
2.如何实现
定义一个抽象基类,抽象基类中应当有至少一个模板方法,在模板方法中提供一些基本的抽象方法,这些抽象方法将在子类中实现。
模板方法一定是final类型,使得用户不得修改模板的具体流程(即好莱坞原则)。
在子类中还可使用钩子方法,来断定某些模板方法中的基本方法是否执行。
3.代码实现
/**
* 抽象基类,为所有子类提供一个算法框架
*/
public abstract class Beverage {
/**
* 制备饮料的模板方法 封装了所有子类共同遵循的算法框架
*/
public final void prepareBeverage() {
// Step 1
boilWater();
// Step 2
brew();
// Step 3
pourInCup();
if (isCustmoerWantsCondiments()) {
// Step 4
addCondiments();
}
}
/**
* 钩子函数,提供一个默认或空的实现
* 具体的子类可以自行决定是否挂钩以及如何挂钩
* 询问用户是否执行
* @return
*/
protected boolean isCustmoerWantsCondiments() {
return true;
}
/**
* 抽象基本方法 加入调料
*/
protected abstract void addCondiments();
/**
* 基本方法 将饮料倒入杯中
*/
private void pourInCup() {
System.out.println("Pour in cup");
}
/**
* 抽象的基本方法,由用户定义 泡制饮料
*/
protected abstract void brew();
/**
* 基本方法,不需要开放过多细节 煮沸水
*/
private void boilWater() {
System.out.println("Boil water");
}
}
/**
* 具体子类,实现咖啡的制备
* @author Anthony
*
*/
public class Coffee extends Beverage {
@Override
protected void addCondiments() {
System.out.println("Add condiments");
}
@Override
protected void brew() {
System.out.println("Brew");
}
@Override
/**
* 子类通过覆盖的形式选择挂载钩子函数
*/
protected boolean isCustmoerWantsCondiments() {
return false;
}
}
public class BeverageTest {
public static void main(String[] args) {
System.out.println("Start");
Beverage b1 = new Coffee();
b1.prepareBeverage();
System.out.println("End");
}
}