模板方法模式(Template method Pattern)
概念:
模板方法模式 在一個方法中定義一個算法的 骨架,而將一些步驟延遲到子類。模板方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟。
組成:
templateMethod(模板方法):定義了某個算法的模板順序或一組步驟,其中任何步驟都可以是抽象的,由子類來實現。
primitiveOperation1(抽象步驟方法):抽象類中聲明,由子類各自實現。
hook(鉤子函數):鉤子是一種被聲明在抽象類中的方法,但只有空的和默認的實現。鉤子的存在,可以讓子類有能力對算法的不同點進行掛鉤。要不要掛鉤由子類自行決定。當我們的子類 “必須” 提供某個方法或步驟的實現時,就使用抽象方法。如果算法的這個部分是可選的,就用鉤子。如果是鉤子的化,子類可以選擇實現這個鉤子,但不強制這麼做。簡單來說 可選的步驟 一般實現爲鉤子函數。
例子:
咖啡店裏的咖啡和茶製作時都有類似的步驟,首先加熱水,然後放入茶或咖啡攪拌(沖泡),然後將飲料倒入杯子,最後加調料。這些步驟是固定的,但固定的步驟中沖泡和加調料兩者分別是不同的。我們現在通過模板方法模式來實現它。
抽象模板方法
public abstract class CoffeeShopBeverage {
//模板方法,製作步驟
final void prepareRecipe() {
boidWater();
brew();
pourInCup();
if (isAddCondiments()) {
addCondiments();
}
}
//沖泡
abstract void brew();
//加調料
abstract void addCondiments();
//固定步驟
void boidWater() {
System.out.println("加熱水...");
}
void pourInCup() {
System.out.println("倒入杯中...");
}
//鉤子函數,來決定是否加調料
boolean isAddCondiments() {
return true;
}
}
咖啡類
public class Coffee extends CoffeeShopBeverage {
@Override
void brew() {
System.out.println("放入咖啡...");
}
@Override
void addCondiments() {
System.out.println("加奶和糖...");
}
}
茶類
public class Tea extends CoffeeShopBeverage {
@Override
void brew() {
System.out.println("放入茶葉...");
}
@Override
void addCondiments() {
System.out.println("加檸檬...");
}
//覆蓋鉤子函數,默認不加檸檬
@Override
boolean isAddCondiments() {
System.out.println("什麼也不加...");
return false;
}
}
測試類:
public class Drink {
public static void main(String[] args) {
Coffee coffee = new Coffee();
System.out.println("Coffee..");
coffee.prepareRecipe();
Tea tea = new Tea();
System.out.println("\nTea...");
tea.prepareRecipe();
}
}
適用場景:
- 一次性實現一個算法的不變的部分,並將可變的行爲留給子類來實現。
- 各子類中公共的行爲應被提取出來並集中到一個公共父類中以避免代碼重複。首先識別現有代碼中的不同之處,並且將不同之處分離爲新的操作。最後,用一個調用這些新的操作的模板方法來替換這些不同的代碼。
- 控制子類擴展。模板方法只在特定點調用“ hook”操作 ,這樣就只允許在這些點進行擴展。
優缺點:
優點:
- 模板方法模式在一個類中形式化地定義算法,而由它的子類實現細節的處理。
- 模板方法是一種代碼複用的基本技術。它們在類庫中尤爲重要,它們提取了類庫中的公共行爲。
- 模板方法模式導致一種反向的控制結構,這種結構有時被稱爲“好萊塢法則” ,即“別找我們,我們找你”通過一個父類調用其子類的操作(而不是相反的子類調用父類),通過對子類的擴展增加新的行爲,符合“開閉原則”。
缺點:
- 每個不同的實現都需要定義一個子類,這會導致類的個數增加,系統更加龐大,設計也更加抽象,但是更加符合“單一職責原則”,使得類的內聚性得以提高。
補充:好萊塢原則
好萊塢原則:別調用(打電話給)我們,我們會調用(打電話給)你。
好萊塢原則是用在創建框架或組件上的一種技巧,好讓底層組件能夠被掛鉤進計算中,而且又不會讓高層組件依賴底層組件。創建一個有彈性的設計,允許底層結構能夠相互操作,而又防止其他類太過依賴它們。
參考:
《Head first 設計模式》