實際開發中常常會遇到,代碼骨架類似甚至相同,只是具體的實現不一樣的場景。例如:流程都有開啟、編輯、駁回、結束。每個流程都包含這幾個步驟,不同的是不同的流程實例它們的內容不一樣。共享單車都是先開鎖、騎行、上鎖、付款。這些大的步驟固定,不同的是每個實例的具體實現細節不一樣。這些類似的業務我們都可以使用模板模式實現。為什么要使用模板模式以及如何使用呢?
介紹
定義:在模板模式(Template Pattern)中,一個抽象類公開定義了執行它的方法的方式/模板。它的子類可以按需要重寫方法實現,但調用將以抽象類中定義的方式進行。這種類型的設計模式屬於行為型模式。
意圖:定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟
主要解決:一些方法通用,卻在每一個子類都重新寫了這一方法。
何時使用:有一些通用的方法。
如何解決:將這些通用算法抽象出來。
關鍵代碼:在抽象類實現,其他步驟在子類實現。
實現
我們以生活中買菜做飯的例子來寫個Demo,燒飯一般都是買菜、洗菜、烹飪、裝盤四大過程。中國自古有八大菜系,制作方式肯定都避不開這四個過程。那在模板模式中如何實現呢?
創建一個抽象類,它的模板方法被設置為 final。為防止惡意操作,一般模板方法都加上 final 關鍵詞。
public abstract class AbstractCookingService {
//買菜
protected abstract void shopping();
//清洗
protected abstract void wash();
//烹飪
protected abstract void cooking();
//裝盤
protected abstract void dishedUp();
public final void process() {
shopping();
wash();
cooking();
dishedUp();
}
}
創建實現了上述抽象類的子類。
// 徽菜烹飪
/**
* 徽菜制作大廚
*/
public class HuiCaiChef extends AbstractCookingService {
@Override
protected void shopping() {
System.out.println("買菜:新鮮魚一條,紅辣椒五兩");
}
@Override
protected void wash() {
System.out.println("清洗:紅椒洗凈切片,魚頭半分");
}
@Override
protected void cooking() {
System.out.println("烹飪:魚頭水蒸,辣椒過油");
}
@Override
protected void dishedUp() {
System.out.println("裝盤:用長形盤子裝盛");
}
}
// 川菜烹制
/**
* 川菜制作大廚
*/
public class HuiCaiChef extends AbstractCookingService {
@Override
protected void shopping() {
System.out.println("買菜:黑豬肉一斤,蒜頭5個");
}
@Override
protected void wash() {
System.out.println("清洗:豬肉洗凈,蒜頭去皮");
}
@Override
protected void cooking() {
System.out.println("烹飪:大火翻炒,慢火悶油");
}
@Override
protected void dishedUp() {
System.out.println("裝盤:深碗盛起,熱油澆拌");
}
}
使用 TemplatePatternDemo 類執行模板方法 process() 來演示烹飪的定義方式。
public class TemplatePatternDemo {
public static void main(String[] args) {
System.out.println("----------川菜制作------------");
AbstractCookingService chuanCaiService = new ChuanCaiChef();
chuanCaiService.process();
System.out.println("-----------徽菜制作-----------");
AbstractCookingService huiCaiService = new HuiCaiChef();
huiCaiService.process();
}
}
執行程序,輸出結果:
----------川菜制作------------
買菜:新鮮魚一條,紅辣椒五兩
清洗:紅椒洗凈切片,魚頭半分
烹飪:魚頭水蒸,辣椒過油
裝盤:用長形盤子裝盛
-----------徽菜制作-----------
買菜:黑豬肉一斤,蒜頭5個
清洗:豬肉洗凈,蒜頭去皮
烹飪:大火翻炒,慢火悶油
裝盤:深碗盛起,熱油澆拌
從以上實例可以看出,其實模板模式也沒什么高深莫測的,簡單來說就是三大步驟:
- 創建一個抽象類,定義幾個抽象方法和一個final修飾的模板方法,而模板方法中設定了抽象方法的執行順序或邏輯。
- 無論子類有多少個,只需要繼承該抽象類,實現父類的抽象方法重寫自己的業務。
- 根據不同的需求創建不同的子類實現,每次調用的地方只需調用模板方法,即可完成特定的模板流程。
總結
從以上的分析和Demo我們可以看到,模板方法提高了我們的代碼的可維護性和可擴展性。有優點也有缺點。
優點: 1、封裝不變部分,擴展可變部分。 2、提取公共代碼,便於維護。 3、行為由父類控制,子類實現。
缺點:每一個不同的實現都需要一個子類來實現,導致類的個數增加,使得系統更加龐大。
使用場景: 1、有多個子類共有的方法,且邏輯相同。 2、重要的、復雜的方法,可以考慮作為模板方法。