設(shè)計模式 ——— 模板方法模式

TEMPLATE METHOD(模板方法) ———— 類行為型模式

意圖

定義一個操作中的算法骨架,而將一些步驟延遲到子類中。TemplateMethod使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。

適用性

  • 需要固定定義算法骨架,實現(xiàn)一個算法的不變的部分,并把可變的行為留給子類來實現(xiàn)的情況;
  • 各個子類中具有公共行為,應(yīng)該抽取出來,集中在一個公共類中去實現(xiàn),從而避免代碼重復(fù);
  • 需要控制子類擴展的情況。模板方法模式會在特定的點來調(diào)用“hook”操作,這樣只允許在這些點進行擴展;

結(jié)構(gòu)

模板方法模式結(jié)構(gòu)圖
  • AbstractClass(抽象類)
    定義抽象的原語操作(primitive operation),具體的子類將重定義它們以實現(xiàn)一個算法的各步驟。
    實現(xiàn)一個模板方法,定義一個算法的骨架。該模板方法不僅調(diào)用原語操作,也調(diào)用定義在AbstractClass或其他對象中的操作。
  • ConcreteClass(具體類)
    實現(xiàn)原語操作以完成算法中與特定子類相關(guān)的步驟。

認識模板方法模式

變與不變

程序設(shè)計的一個很重要的思考點就是“變與不變”,也就是分析程序中哪些功能是可變的,哪些功能是不變的,然后把不變的部分抽象出來,進行公共的實現(xiàn),把變化的部分分離出去,用接口來封裝隔離,或者是用抽象類來約束子類行為。

模板方法模式很好的體現(xiàn)了這一點。模板類實現(xiàn)的就是不變的方法和算法的骨架,而需要變化的地方,都通過抽象方法,把具體實現(xiàn)延遲到子類去了,而且還通過父類的定義來約束了子類的行為,從而使系統(tǒng)能有更好的復(fù)用性和擴展性。

好萊塢法則

什么是好萊塢法則呢?簡單點說,就是“不要找我們,我們會聯(lián)系你”。

模板方法模式很好的體現(xiàn)了這一點,做為父類的模板會在需要的時候,調(diào)用子類相應(yīng)的方法,也就是由父類來找子類,而不是讓子類來找父類。

這其實也是一種反向的控制結(jié)構(gòu),按照通常的思路,是子類找父類才對,也就是應(yīng)該是子類來調(diào)用父類的方法,因為父類根本就不知道子類,而子類是知道父類的,但是在模板方法模式里面,是父類來找子類,所以是一種反向的控制結(jié)構(gòu)。

對設(shè)計原則的體現(xiàn)

模板方法很好的體現(xiàn)了開閉原則和里氏替換原則。

首先從設(shè)計上,先分離變與不變,然后把不變的部分抽取出來,定義到父類里面,比如算法骨架,比如一些公共的、固定的實現(xiàn)等等。這些不變的部分被封閉起來,盡量不去修改它了,要擴展新的功能,那就使用子類來擴展,通過子類來實現(xiàn)可變化的步驟,對于這種新增功能的做法是開放的。

其次,能夠?qū)崿F(xiàn)統(tǒng)一的算法骨架,通過切換不同的具體實現(xiàn)來切換不同的功能,一個根本原因就是里氏替換原則,遵循這個原則,保證所有的子類實現(xiàn)的是同一個算法模板(為了防止子類改變模板方法中的算法,可以將模板方法聲明為final),并能在使用模板的地方,根據(jù)需要,切換不同的具體實現(xiàn)。

模板方法模式的實現(xiàn)

模板方法調(diào)用下列類型的操作
  • 模板方法:就是定義算法骨架的方法 。
  • 具體的操作:在模板中直接實現(xiàn)某些步驟的方法,通常這些步驟的實現(xiàn)算法是固定的,而且是不怎么變化的,因此就可以當(dāng)作公共功能實現(xiàn)在模板里面。如果不需提供給子類訪問這些方法的話,還可以是private的。這樣一來,子類的實現(xiàn)就相對簡單些。如果是子類需要訪問,可以把這些方法定義為protected final的,因為通常情況下,這些實現(xiàn)不能夠被子類覆蓋和改變了。
  • 具體的AbstractClass操作:在模板中實現(xiàn)某些公共功能,可以提供給子類使用,一般不是具體的算法步驟的實現(xiàn),只是一些輔助的公共功能。
  • 原語操作:就是在模板中定義的抽象操作,通常是模板方法需要調(diào)用的操作,是必需的操作,而且在父類中還沒有辦法確定下來如何實現(xiàn),需要子類來真正實現(xiàn)的方法。
  • 鉤子操作:在模板中定義,并提供默認實現(xiàn)的操作。這些方法通常被視為可擴展的點,但不是必須的,子類可以有選擇的覆蓋這些方法,以提供新的實現(xiàn)來擴展功能。比如:模板方法中定義了5步操作,但是根據(jù)需要,某一種具體的實現(xiàn)只需要其中的1、2、3這幾個步驟,因此它就只需要覆蓋實現(xiàn)1、2、3這幾個步驟對應(yīng)的方法。那么4和5步驟對應(yīng)的方法怎么辦呢,由于有默認實現(xiàn),那就不用管了。也就是說鉤子操作是可以被擴展的點,但不是必須的。
  • Factory Method:在模板方法中,如果需要得到某些對象實例的話,可以考慮通過工廠方法模式來獲取,把具體的構(gòu)建對象的實現(xiàn)延遲到子類中去。

模板方法模式實現(xiàn)中指的注意的問題:

① 使用訪問控制:必須重定義的原語操作須定義為abstract函數(shù)。模板方法自身不需要被重定義,并且也不應(yīng)該被重定義,為了防止子類改變模板方法中的算法,可以將模板方法聲明為final。
② 盡量減少原語操作:定義模板方法的一個重要目的是盡量減少一個子類具體實現(xiàn)算法時必須重定義的那些原語操作的數(shù)目。需要重定義的操作越多,客戶程序就越冗長。
③ 命名約定:可以給應(yīng)被重定義的那些操作的名字加上一個前綴以識別它們。

優(yōu)缺點

優(yōu)點:
實現(xiàn)代碼復(fù)用
模板方法模式是一種實現(xiàn)代碼復(fù)用的很好的手段。通過把子類的公共功能提煉和抽取,把公共部分放到模板里面去實現(xiàn)。

缺點:
算法骨架不容易升級
模板方法模式最基本的功能就是通過模板的制定,把算法骨架完全固定下來。事實上模板和子類是非常耦合的,如果要對模板中的算法骨架進行變更,可能就會要求所有相關(guān)的子類進行相應(yīng)的變化。所以抽取算法骨架的時候要特別小心,盡量確保是不會變化的部分才放到模板中。

相關(guān)模式

  • 模板方法模式 VS 工廠方法模式
    這兩個模式可以配合使用。
    模板方法模式可以通過工廠方法來獲取需要調(diào)用的對象。

  • 模板方法模式 VS 策略模式
    模板方法會定義一個算法的大綱,然后由子類通過繼承來實現(xiàn)其中某些步驟的內(nèi)容;策略模式則是通過對象組合的方式,讓客戶可以選擇算法實現(xiàn)。即,使用委托來改變整個算法。

    但是,我們可以在模板方法中使用策略模式,就是把那些變化的算法步驟通過使用策略模式來實現(xiàn),但是具體選取哪個策略還是要由外部來確定,而整體的算法步驟,也就是算法骨架就由模板方法來定義了。

參考

《Head First 設(shè)計模式》
《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》
《研磨設(shè)計模式》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內(nèi)容