1. 定義
模板方法模式是類的行為模式。準備一個抽象類,將部分邏輯以具體方法以及具體構造函數的形式實現,然后聲明一些抽象方法來迫使子類實現剩余的邏輯。不同的子類可以以不同的方式實現這些抽象方法,從而對剩余的邏輯有不同的實現。這就是模板方法模式的用意。
簡單理解
- 模板方法
一個模板方法是定義在抽象類中的,把基本操作方法組合在一起形成一個總算法或一個總行為的方法。
一個抽象類可以有任意多個模板方法,而不限于一個。每一個模板方法都可以調用任意多個具體方法。 - 基本方法
基本方法又可以分為三種:抽象方法(Abstract Method)、具體方法(Concrete Method)和鉤子方法(Hook Method)。
● 抽象方法:一個抽象方法由抽象類聲明,由具體子類實現。在Java語言里抽象方法以abstract關鍵字標示。
● 具體方法:一個具體方法由抽象類聲明并實現,而子類并不實現或置換。
● 鉤子方法:一個鉤子方法由抽象類聲明并實現,而子類會加以擴展。通常抽象類給出的實現是一個空實現,作為方法的默認實現。 - 默認鉤子方法
一個鉤子方法常常由抽象類給出一個空實現作為此方法的默認實現。這種空的鉤子方法叫做“Do Nothing Hook”。顯然,這種默認鉤子方法在缺省適配模式里面已經見過了,一個缺省適配模式講的是一個類為一個接口提供一個默認的空實現,從而使得缺省適配類的子類不必像實現接口那樣必須給出所有方法的實現,因為通常一個具體類并不需要所有的方法。
2. 簡單實例
假如你是一個店員,店理由咖啡和茶,你為顧客準備不同的飲品的時候,基本方法如下:
- 準備沸水
- 用沸水沖泡咖啡或茶葉
- 用合適的杯子把咖啡或者茶裝起來
- 加上一些合適的調料
很顯然,上面四個步驟中步驟1和3都是一樣的,沸水、杯子;步驟2和4不同,咖啡或者茶葉、抹茶或者奶蓋;
所以我們可以把相同的步驟放到基類,把不同的步驟讓子類去實現,另外加個鉤子函數,讓子類去重寫,實現不同的邏輯;
3. 具體代碼實現
- 首先把共同的方法封裝在基類中
"Drink作為一個父類,把共通的方法定義并實現,子類不能去修改;然后定義抽象的方法,讓子類去實現。"
public abstract class Drink {
public void prepareDrink() {
BoilingWater();
Brewing();
cups();
if (isAddOthers()) {
seasoning();
}
}
//沸水
private void BoilingWater() {
System.out.println("BoilingWater 水已經沸騰了。。。");
}
//沖泡咖啡或者茶,具體子類去實現
public abstract void Brewing();
//都用杯子裝起來
private void cups() {
System.out.println("cups 找個杯子裝起來。。。");
}
//子類決定加什么調料
public abstract void seasoning();
public boolean isAddOthers() {
return true;
}
}
- 不同的子類,繼承父類,并實現自己的邏輯
"咖啡:拿鐵、奶"
public class Coffee extends Drink{
@Override
public void Brewing() {
System.out.println("Brewing 來一杯拿鐵...");
}
@Override
public void seasoning() {
System.out.println("seasoning 拿鐵多加點奶...");
}
}
"茶:紅茶、奶蓋"
public class Tea extends Drink{
@Override
public void Brewing() {
System.out.println("Brewing 我們來一壺紅茶...");
}
@Override
public void seasoning() {
System.out.println("seasoning 紅茶加點奶蓋吧...");
}
@Override
public boolean isAddOthers() {
//子類可以重寫該方法,來決定是不是添加其他的東西
return true;
}
}
- 調用方式
//茶
Tea tea = new Tea();
tea.prepareDrink();
//咖啡
Coffee coffee = new Coffee();
coffee.prepareDrink();
- 輸出結果
"茶"
I/System.out(25585): BoilingWater 水已經沸騰了。。。
I/System.out(25585): Brewing 我們來一壺紅茶...
I/System.out(25585): cups 找個杯子裝起來。。。
I/System.out(25585): seasoning 紅茶加點奶蓋吧...
"咖啡"
I/System.out(25585): BoilingWater 水已經沸騰了。。。
I/System.out(25585): Brewing 來一杯拿鐵...
I/System.out(25585): cups 找個杯子裝起來。。。
I/System.out(25585): seasoning 拿鐵多加點奶...
4. 總結
模板方法模式總結起來就是:父類定義并實現公共的方法,并且子類不能修改;對于子類之間的差異,增加抽象的方法,讓子類去實現自己的邏輯,互不干擾;并且子類可以通過重寫父類的特定方法(上面的鉤子方法),來決定是否執行某個步驟或者方法。