模板方法模式 Template method 行爲型 設計模式(二十六)

模板方法模式 Template method
image_5c230441_24ee
上圖爲網上百度的一份簡歷模板截圖
 
image_5c230441_1b35
相信你們都有求職的經歷,那麼必然須要簡歷,寫簡歷的時候,極可能你會網上檢索一份 簡歷模板,使用此模板的格式,而後替換爲你的內容。 
 
咱們從小就有語文課,逢考必有做文,而學習的途徑之一就是參考優秀的 範文,學習瞭解他們的結構,風格等。
image_5c230441_782a
以上就是現實世界中的模板,模板的概念隨處可見,全部的工業製品哪一個不是 模具生產的?
 
在程序設計中,也有模板的概念
在軟件開發過程當中,可能常常會用到相似的處理邏輯,可是可能又有一些細節的差別
好比作菜,無論作什麼菜,基本上都離不開買菜,洗菜,切菜,作菜幾個主要步驟
這幾個步驟中,只有作菜的差異最大,不一樣的菜不一樣的作法,而買菜洗菜切菜的過程,卻基本相似
 
咱們經常但願可以 定義一個通用的處理框架,而後將一部分實現細節交由子類進行處理
也就是 面向框架進行編程,而不是每次都複製粘貼修改代碼,具體的細節依靠子類肯定,這就是模板的初衷。 
 
好比定義一個作菜的抽象類,實現了買菜,洗菜,切菜,作菜方法定義爲抽象方法留待子類實現
那麼,回鍋肉和大頭菜就能夠經過繼承擴展作菜類,只須要實現作菜的環節便可。

意圖

定義一個操做中的算法的骨架,而將一些步驟延時到子類中。
TemplateMethod使得子類能夠不改變一個算法的結構便可從新定義算法的某些特定步驟。

結構

image_5c230441_6923
 
抽象模板角色AbstractClass
定義一個或者多個抽象步驟,這些抽象操做叫作基本操做
他們多是一個複雜操做的組成步驟
實現類角色ConcreteClass
實現父類所定義的一個或者多個抽象方法
 
每個抽象模板均可以有任意多個具體的模板角色與之對應,而實際中,通常不止一個

代碼示例

定義作菜步驟:買菜,洗菜,切菜,作菜。
買菜、洗菜、切菜都同樣,作菜不一樣菜不一樣作法
上菜將他們步驟進行打包
package template;
 
public abstract class 作菜 {
    public void 買菜(){
        System.out.println("買菜...");
    }
    public void 洗菜(){
        System.out.println("洗菜...");
    }
    public void 切菜(){
        System.out.println("切菜...");
    }
    public abstract void 作菜();
     
    public void 上菜(){
        買菜();
        洗菜();
        切菜();
        作菜();
        System.out.println("客官,菜來了~~~");
    }
}
作回鍋肉和作大頭菜都重寫了「作菜」的方法
package template;
 
public class 作回鍋肉 extends 作菜 {
@Override
public void 作菜() {
System.out.println("作回鍋肉...");
}
}

 

package template;
public class 作大頭菜 extends 作菜 {
@Override
public void 作菜() {
System.out.println("作大頭菜...");
}
}

測試代碼html

image_5c230442_6920

方法分類

一般模板模式中會涉及到兩類方法,模板方法和基本方法
模板方法指的是定義在抽象類中,把基本方法組合在一塊兒造成複雜邏輯的方法,一般子類是不修改這個方法的
模板方法給出來頂層的邏輯框架。
好比上面的「上菜」,上菜方法調用了「買菜,洗菜,切菜,作菜」
能夠有任意多個的模板方法
 
另外一類就是 基本方法了,基本方法就是複雜方法的組成部分
基本方法又有幾種形式
抽象方法,具體方法,鉤子方法
抽象方法:abstract定義,子類實現
具體方法:抽象類具體實現
鉤子方法:抽象類提供默認實現的方法,常常是一個空實現,好處是子類不是必須實現
 
前面說到,模板方法定義了頂層的框架邏輯,並且子類通常不修改,直接繼承。
能夠經過鉤子方法對頂層框架邏輯進行微調
好比上面作菜的示例中,上菜的環節中,新增長一個方法用來判斷是否須要切菜
image_5c230442_711e
 
作大頭菜類中,重寫這個方法,作大頭菜,不切了
image_5c230442_6905
 
再來看看打印結果,大頭菜,沒切就作了。。。。。
image_5c230442_1cd4

總結

模板方法模式的根本在於共性的提取與解題步驟框架化
一般使用繼承機制完成這一目標
 
繼承使得類型的等級結構易於理解,井井有條,很是適合抽象化的設計
可是 繼承隨之而來的強耦合,也將會致使不少的不便,好比打破了封裝,父類向子類暴露
不能在運行時動態更改,父類改變,子類極可能也須要改變
因此繼承是一把雙刃劍,使用不當也會致使很大的問題。
可是,不能因噎廢食,我的認爲對繼承的態度應該是 不濫用,不棄用
 
模板模式也能夠用於方法層次上 方法的拆解,若是一個方法中有不少的代碼邏輯步驟
那麼,能夠藉助於模板模式定義解題步驟,將步驟進行拆解
好比原方法爲
step()
拆分後爲
step(){
  step1();
  step2();
  ....
}
原來的step的方法就至關於抽象類,step1,step2就至關於具體的子類
 
模板模式的根本就是共性的提取以及解題步驟框架化(就是步驟分明處理)
因此千萬不要認爲模板就僅僅只是繼承,實現接口就表示模板的概念了麼?我的認爲仍舊是
沒有模板方法,僅僅是基本方法就不是模板模式了麼?我的認爲仍舊是
模板方法仍舊是依賴倒置原則的實現方案。
只不過模板模式相對於面向抽象編程,又進一步指望父類提供更多給子類,好比算法邏輯框架
將部分職責延遲到子類。
 
藉助於鉤子方法的形式,能夠引入更多的靈活性,子類能夠對父類的總體邏輯作出微調
達到了反向控制的效果---子類控制了父類方法的細節步驟
 
涉及到共性提取或者框架步驟分割的均可以考慮模板模式
相關文章
相關標籤/搜索