什么是模板方法模式
正式定义
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板方法定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。
一个模板方法的实现:
一个咖啡因饮料的准备方法:
final void prepareRecipe(){
boilWater();
brew();
pourInCup();
addCondiments();
}
对应茶和咖啡来说,他们的煮沸水和倒杯子方法是相同的,可直接在该类里实现,其他不同的方法定义为抽象的,可在对应的子类实现:
public class Tea extends CaffeineBeverage {
public void brew(){
System.out.println("Steeping the tea");
}
public void addCondiments(){
System.out.println("Adding lemon");
}
}
模板方法就是将算法定义为一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现,这可以确保算法的结构保持不变,同时由子类提供部分实现。
对模板方法挂钩
钩子(hook)是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩,要不要挂钩,由子类自行决定。
有了钩子,子类可以决定是否覆盖抽象类的方法,如果不覆盖,抽象类提供一个默认实现。
下面是一种钩子的实现:
先在抽象类中加入钩子:
public abstract class CaffeeineBeverageWithHook {
void prepareRecipe(){
boilWater();
brew();
pourInCup();
if(customerWantsCondiments()){
addCondiments();
}
}
abstract void brew();
abstract void addCondiments();
void boilWater(){
System.out.println("Boiling water");
}
void pourInCup(){
System.out.println("Pouring into cup");
}
boolean customerWantsCondiments(){ //钩子
return true;
}
}
子类实现钩子的方法:
public class CoffeeWithHook extends CaffeeineBeverageWithHook {
public void brew(){
System.out.println("Dripping coffee through filter");
}
public void addCondiments(){
System.out.println("Adding sugar and milk");
}
public boolean customerWantsCondiments() {
String answer = getUserInput();
if(answer.toLowerCase().startsWith("y"))
return true;
else
return false;
}
private String getUserInput() {
String answer = null;
System.out.println("Would you like milk and sugar with your coffee (y/n) ? ");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
answer = in.readLine();
}catch (IOException e){
e.printStackTrace();
}
if(answer == null)
return "no";
return answer;
}
}
- 当子类必须实现算法中的某个方法时,就用抽象方法,如果这部分是可选的,就用钩子;
- 钩子的另一个用法是让子类能够有机会对模板方法中某些即将发生的步骤做出反应。