前言:
來源於《head first 設計模式》。當作讀書筆記了,這次看的是第8章模版方法模式。難頂呀每晚看完書,第二天早上總結。理解到了以前學習java、spring中的一些基礎的概念,蠻有用的,希望自己可以一直堅持下去吧。
模版方法模式的概念
在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模版方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟
適配器模式的uml圖
- AbstractClass:在templateMethod中定義了算法的骨架,具體的實現方法operation1、2交給子類來實現
- ConcreteClass:實現operation1、2算法。
例子: - 咖啡沖泡法:
1.把水煮沸
2.用沸水沖泡咖啡
3.把咖啡倒進杯子
4.加糖和牛奶 - 茶沖泡法
1.把水煮沸
2.用沸水沖泡茶葉
3.把茶倒進杯子
4.加檸檬
茶和咖啡的基類—AbstractClass
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");
}
}
coffee和茶的實現類
實現對應的算法骨架中,自己改變的那部分方法。
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");
}
}
hook鉤子方法的使用
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;
}
}
hook方法子類實現
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();
System.out.println("\nMaking tea...");
teaHook.prepareRecipe();
}
}
總結
Java中也有模板方法的體現。那就是對數組進行排序的時候實現Comparable接口,提供這個接口所聲明的compareTo()方法。
策略模式與模版模式的不同:
則略模式:針對整個算法的實現,用所組合的類實現了整個算法,委託的方式實現。
模版模式:針對算法中的每個步驟,採用繼承的形式來實現,讓子類來重寫需要修改的算法步驟。