1 概述
模板方法模式(Template Method Pattern)是一種很常見的行爲模式。在超類/抽象類中創建一個模板方法,方法中定義一個算法步驟或框架,讓子類在不修改主結構的情況下,重寫其中的子步驟。
2 模板方法模式
假如存在一系列對象的方法,他們的步驟是大體一致的,區別只是其中的一個子步驟。這種情況會導致大量重複冗餘的代碼,當公共部分需要改變時,不得不修改所有相關的對象。如果用模版方法模式改造,可以簡化邏輯:將其中不變的部分抽離出來,作爲一個模板方法,然後讓子類只實現差異化的部分代碼。
比如,前面舉過的例子中,網上購物結算可以有多種途徑,支付寶,微信等等,所以對於“網上購物”,運用模板方法模式的思想,便可以將挑選商品,加入購物車,提交訂單,支付結算這幾個步驟,定義成模板方法。其中,前面三個步驟是通用的,最後一個方法,留給子類根據不同的支付方式去實現自己的邏輯。
一般情況下,模板方法應該定義爲final
,因爲它包含了算法的框架,不應該被子類覆蓋重寫。類似的,需要子類重寫的差異化方法,需要定義爲abstract
。
3 案例
看一個案例加深理解。做披薩的一般順序是:做披薩皮,加澆頭,烘焙。披薩是什麼口味,完全看澆頭是什麼,所以,我們可以用模版方法模式來“製作披薩”:
public abstract class PizzaCook {
public final void bakePizza() {
processCrust();
processTopping();
bake();
System.out.println("Pizza is now baked!!!");
}
private void processCrust() {
System.out.println("Crust is ready...");
}
private void bake() {
System.out.println("Putting the pizza to oven...");
};
protected abstract void processTopping();
}
public class FruitPizzaCook extends PizzaCook {
@Override
protected void processTopping() {
System.out.println("Putting some fruit on the Pizza...");
}
}
public class BaconPizzaCook extends PizzaCook {
@Override
protected void processTopping() {
System.out.println("Putting the bacon on the Pizza...");
}
}
public class Test {
public static void main(String[] args) {
PizzaCook fruitPizzaCook = new FruitPizzaCook();
fruitPizzaCook.bakePizza();
System.out.println("--------------");
PizzaCook baconPizzaCook = new BaconPizzaCook();
baconPizzaCook.bakePizza();
}
}
輸出:
Crust is ready...
Putting some fruit on the Pizza...
Putting the pizza to oven...
Pizza is now baked!!!
--------------
Crust is ready...
Putting the bacon on the Pizza...
Putting the pizza to oven...
Pizza is now baked!!!
父類中定義了披薩的製作步驟,作爲子類,只需要實現processTopping()
方法。模板方法模式省去了很多重複代碼,方便了代碼重用。當公共部分(processCrust()
/bake
)需要改動時,只需要改動父類即可。
JDK
中,所有的List
都繼承了AbstractList,所有的Set
都繼承了AbstractSet,所有的Map
都繼承了AbstractMap,模板方法模式在這三個類中得到了很好的運用。
4 總結
模板方法模式通過將方法的步驟抽象分離,封裝不變部分,擴展可變部分,減少了冗餘代碼,方便了維護。