1. 应用场景
模板模式就是通过抽象类来定义一个逻辑模板,逻辑框架、逻辑原型,然后将无法决定的部分抽象成抽象类交由子类来实现,一般这些抽象类的调用逻辑还是在抽象类中完成的。这么看来,模板就是定义一个框架,比如盖房子,我们定义一个模板:房子要封闭,有门,有窗等等,但是要什么样的门,什么样的窗,这些并不在模板中描述,这个交给子类来完善,比如门使用防盗门,窗使用北向的窗等等。
2. 概念
定义算法框架,并将一些步骤的实现延迟到子类。通过模板方法,子类可以重新定义算法的某些步骤,而不用改变算法的结构。
3. Class Digram
这个抽象类中包含了模板方法。这个模板方法所用到的操作的抽象版本。模板方法在实现的过程中,用到了这两个原语操作。模板方法本身和这两个操作的具体实现之间解耦了。可能有许多的具体类,每一个都实现了模板方法所需要的全部操作。这个具体类实现抽象的操作,当模板方法需要这里两个抽象方法时,会调用他们。
4. Implementation
冲咖啡和冲茶都有类似的流程,但是某些步骤会有点不一样,要求复用那些相同步骤的代码。
public abstract class CaffeineBeverageWithHook {
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
abstract void brew();
abstract void addCondiments();
public void boilWater() {
System.out.println("Boiling water");
}
public void pourInCup() {
System.out.println("Pouring into cup");
}
public boolean customerWantsCondiments() {
return true;
}
}
public class CoffeeWithHook extends CaffeineBeverageWithHook{
@Override
void brew() {
System.out.println("Dripping Coffee through filter");
}
@Override
void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
@Override
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 bufferedReader=new BufferedReader(new InputStreamReader(System.in));
try {
answer=bufferedReader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
if(answer==null){
return "no";
}
return answer;
}
}
public class TeaWithHook extends CaffeineBeverageWithHook {
public void brew() {
System.out.println("Steeping the tea");
}
public void addCondiments() {
System.out.println("Adding Lemon");
}
public boolean customerWantsCondiments() {
String answer = getUserInput();
if (answer.toLowerCase().startsWith("y")) {
return true;
} else {
return false;
}
}
private String getUserInput() {
// get the user's response
String answer = null;
System.out.print("Would you like lemon with your tea (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;
}
}
public class BeverageTestDrive {
public static void main(String[] args) {
Tea tea = new Tea();
Coffee coffee = new Coffee();
System.out.println("\nMaking tea...");
tea.prepareRecipe();
System.out.println("\nMaking coffee...");
coffee.prepareRecipe();
TeaWithHook teaHook = new TeaWithHook();
CoffeeWithHook coffeeHook = new CoffeeWithHook();
System.out.println("\nMaking tea...");
teaHook.prepareRecipe();
System.out.println("\nMaking coffee...");
coffeeHook.prepareRecipe();
}
}
运行结果:
Making tea...
Boiling water
Steeping the tea
Pouring into cup
Adding Lemon
Making coffee...
Boiling water
Dripping Coffee through filter
Pouring into cup
Adding Sugar and Milk
Making tea...
Boiling water
Steeping the tea
Pouring into cup
Would you like lemon with your tea (y/n)? y
Adding Lemon
Making coffee...
Boiling water
Dripping Coffee through filter
Pouring into cup
Would you like milk and sugar with your coffee (y/n) ?
n