定义一个模板抽象类,算法固定,个别函数抽象,可以在不改变算法结构的情况下在子类中重新定义算法的步骤。
我们来看看这个抽象类如何定义:
Abstract class AbstractClass {
Abstract void primitiveOperation1(); //继承后可修改具体实现
Abstract void primitiveOperation2();
Void concreteOperation(){ //被所有子类或模板方法直接调用的方法;
}
Final void templateOperation(){ //模板方法,整个算法结构以及功能固定;
primitiveOperation1();
primitiveOperation2();
concreteOperation();
}
Void hook(){ //留给子类的继承接口,可用来增加自己对算法的条件修改;我们叫做钩子
}
}
我们看一下例子:泡咖啡和冲饮料基本步骤都是一样的,只是每个步骤地操作不同,我们用模板方法模式来实现:
public abstract class CaffeineBeverageWithHook {
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;
}
//hook函数,子类可覆盖
}
我们来看看如何泡咖啡:
public class Coffee extends CaffeineBeverageWithHook {
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.print("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 ioe) {
System.err.println("IO error trying to read your answer");
}
if (answer == null) {
return "no";
}
return answer;
}
}
我们看到 覆盖了customerWantsCondiments.增加了与用户确定调料的判断.这就是钩子的作用;
我们来写了测试类:
public static void main(String[] args) {
Coffee coffee = new Coffee();
System.out.println("\nMaking coffee...");
coffee.prepareRecipe();
}
}
同样可以在写个TEA类继承CaffeineBeverageWithHook,实现同Coffee。
我们在延伸一下:
JFrame,Applet都是模板模式,定义了整个生命周期,我们在开始时总是这样:
public class MyApplet extends Applet{}去实现各个生命周期的方法。
模板方法和策略方法的比较:
相同点:二者都是提供算法
不同:模板使用继承,策略使用组合,利用接口;
工厂方法是模版方法的一种情况,还记得吗?
Public Abstract class FactoryMethod{
Abstract void createFactory();
void FactoryMethodOperation(){ //模板方法,整个算法结构以及功能固定;
}
}
工厂方法将实例的创建推迟到子类中。