在程式開發中,經常會遇到這種情況:某個方法要實現的演算法需要多個步驟,但其中有一些步驟是固定不變的,而另一些步驟則是不固定的。為了提高**的可擴充套件性和可維護性,模板方法模式在這種場景下就派上了用場。
定義乙個操作中演算法的框架,而將一些步驟延遲到子類中。模板方法模式使得子類可以不改變乙個演算法的結構即可重定義該演算法的某些特定步驟。模板方法模式是一種基於繼承的**復用技術,它是一種類行為型模式。
模板方法模式是用來建立乙個演算法模板,什麼是模板?其實就是乙個方法。更加具體的來說就是這個方法將演算法定義成一組固定順序的步驟,其中任何一種步驟都可以是抽象的,由子類負責實現,如果這些步驟中的方法是子類共用的,就由父類實現,子類直接繼承即可。這樣可以確認演算法的結構保持不變,同時由子類提供部分實現。
abstractclass(抽象類)
抽象類中定義了兩種方法:模板方法(template method),基本操作(primitiveoperations)、
1. 模板方法(template method):用於定義乙個演算法的框架,模板方法不僅可以呼叫在抽象類中實現的基本方法,也可以呼叫在抽象類的子類中實現的基本方法,還可以呼叫其他物件中的方法。
模板方法是乙個具體方法,它給出了乙個頂層邏輯框架,而邏輯的組成步驟在抽象類中可以是具體方法,也可以是抽象方法。為防止惡意操作,通常模板方法被定義成final,不允許子類改變。2. 基本操作(primitive operations):基本操作可以是具體的,也可以是抽象的,每乙個基本操作對應演算法的乙個步驟,是模板方法的組成部分,在其子類中可以重定義或實現這些步驟。基本操作可以分為以下3種:
(1)抽象方法(abstract method)
乙個抽象方法由抽象類宣告、由其具體子類實現。
(2)具體方法(concrete method)
乙個具體方法由乙個抽象類或具體類宣告並實現,其子類可以進行覆蓋也可以直接繼承。
(3)鉤子方法(hook method)
可以與一些具體步驟 「掛鉤」 ,以實現在不同條件下執行模板方法中的不同步驟;我們可以在父類中確定整個流程的順序,並實現固定不變的步驟,而把不固定的步驟留給子類實現。甚至可以通過乙個鉤子方法,讓子類來決定流程中某個方法的執行與否
hook方法在抽象類中的實現為空,是留給子類做一些可選的操作。如果某個子類需要一些特殊額外的操作,則可以實現hook方法,當然也可以完全不用理會,因為hook在抽象類中只是空方法而已。
1)鉤子方法的引入使得子類可以控制父類的行為。
2)最簡單的鉤子方法就是空方法,也可以在鉤子方法中定義乙個預設的實現,如果子類不覆蓋鉤子方法,則執行父類的預設實現**。
3)比較複雜一點的鉤子方法可以對其他方法進行約束,這種鉤子方法通常返回乙個布林型別,用來判斷是否執行某乙個基本方法。由子類來決定是否呼叫hook方法。
concreteclass(具體子類)
它是抽象類的子類,用於實現在父類中宣告的抽象基本操作以完成子類特定演算法的步驟,也可以覆蓋在父類中已經實現的具體基本操作。
例子:
我們將建立乙個定義操作的 game 抽象類,其中,模板方法固定了玩遊戲的基本步驟,初始化遊戲、開始玩遊戲、結束遊戲是必要的步驟,而遊戲中休息則是選擇性的,我們將模板方法設定為 final,這樣它就不會被重寫,增加乙個鉤子函式,然後使用者去決定是否在遊戲中休息。basketball 和 football 是擴充套件了 game 的實體類,它們重寫了抽象類的方法,**如下:
#include
using
namespace std;
class
game
/* 宣告為final表示演算法骨架不能被子類改變 */
virtual
void
playgame
() final
endplay()
;}};
class
football
:public game
void
startplay
() override
void
rest
() override
void
endplay
() override
bool
needresthook
() override };
class
basketball
:public game
void
startplay
() override
void
rest
() override
void
endplay
() override
bool
needresthook
() override };
intmain()
1. 優點(1)在父類中定義乙個固定的演算法框架,而由它的子類來實現細節的處理,在子類實現詳細的處理演算法時並不會改變演算法中步驟的執行次序。
(2)模板方法模式是一種**復用技術,它在類庫設計中尤為重要,它提取了類庫中的公共行為,將公共行為放在父類中,而通過其子類來實現不同的行為,它鼓勵我們恰當使用繼承來實現**復用。
(3)可實現一種反向控制結構,通過子類覆蓋父類的鉤子方法來決定某一特定步驟是否需要執行。
(4)在模板方法模式中可以通過子類來覆蓋父類的基本方法,不同的子類可以提供基本方法的不同實現,更換和增加新的子類很方便,符合單一職責原則和開閉原則。
2. 缺點
(1)需要為每乙個基本方法的不同實現提供乙個子類,如果父類中可變的基本方法太多,將會導致類的個數增加,系統更加龐大,設計也更加抽象。
3. 適用場景
(1)對一些複雜的演算法進行分割,將其演算法中固定不變的部分設計為模板方法和父類具體方法,而一些可以改變的細節由其子類來實現。即:一次性實現乙個演算法的不變部分,並將可變的行為留給子類來實現。
(2)各子類中公共的行為應被提取出來並集中到乙個公共父類中以避免**重複。
(3)需要通過子類來決定父類演算法中某個步驟是否執行,實現子類對父類的反向控制。
4. 模板方法模式與策略模式
模板方法使用繼承來改變演算法的一部分。 strategy使用委託來改變整個演算法。模板方法模式與策略模式的作用十分類似,有時可以用策略模式替代模板方法模式。模板方法模式通過繼承來實現**復用,而策略模式使用委託,把不確定的行為集中到乙個介面中,並在主類委託這個介面。委託比繼承具有更大的靈活性。
設計模式(4) 模板方法模式
模板方法模式 定義 定義乙個操作中的演算法框架,而將一些步驟延遲到子類中。使得子類能夠不改變乙個演算法的結構就可以重定義該演算法的某些特定步驟。模板方法模式很easy,只使用了j a的繼承機制,但它是乙個應用很廣泛的模式。在軟體開發project中,假設同樣一段 複製過兩次,就須要對設計產生懷疑。架...
設計模式 c 版(4) 模板方法模式
定義 定義乙個操作中的演算法的框架,而將一些步驟延遲到子類中。使得子類可以不改變乙個演算法的結構即可重定義該演算法的某些特定步驟。abstractclass 叫抽象模板,他的方法分為兩類 基本方法 即基本操作,是由子類實現的方法,並且在模板方法被呼叫。模板方法 可以有乙個或幾個,一般是乙個具體方法,...
C 實現 設計模式 4 模板方法模式
參考書籍 公司接到乙個xx模型公司的的訂單 需要生產10萬悍馬的車模 只做基本的實現 不靠慮擴充套件性 那麼就開始埋頭幹 先按照最一般的經驗設計類圖 如圖所示 非常簡單的實現 悍馬車有兩個型號 h1和h2 按照需求 只需要悍馬模型 那就給你悍馬模型 先寫乙個抽象類 然後兩個不同型號的模型實現類 通過...