模板方法模式是一種基於繼承的**復用的行為型模式;在其結構中只存在父類與子類之間的繼承關係。通過使用模板方法模式,可以將一些複雜流程的實現步驟封裝在一系列基本方法中,在抽象父類中提供乙個稱之為模板方法的方法來定義這些基本方法的執行次序,而通過其子類來覆蓋某些步驟,從而使得相同的演算法框架可以有不同的執行結果。本篇部落格我們一起來學習模版方法模式。
代表這些具體邏輯步驟的方法稱做基本方法(primitive method);而將這些基本方法彙總起來的方法叫做模板方法(template method),這個設計模式的名字就是從此而來。
定義
對於模板方法模式,父類提供的構建步驟和順序或者演算法骨架,通常是不希望甚至是不允許子類去覆蓋的,所以在某些場景中,可以直接將父類中提供骨架的方法宣告為final型別。
優點
缺點
每乙個不同的實現都需要乙個子類來實現,導致類的個數增加,使得系統更加龐大
使用場景
舉乙個去餐館吃飯的例子:
#include#includeusing namespace std;
//有兩個人(小紅和小明)去吃飯,首先定義這兩個人的抽象類:
class person
; //開餐。
virtual void eat() = 0;
};//小紅的定義如下:
class personhong : public person
void drinksomthing()override
public:
void eat() override };
//小明的定義如下:
class personming : public person
void drinksomthing()override
public:
void eat() override };
//客戶端呼叫:
這裡我們會發現,小紅和小明的行為中都有 eat() 方法,這時我們就很容易地想到使用繼承機制,將 eat() 方法放到 person 類中:
#include#includeusing namespace std;
class person
; //開餐。
virtual void eat() // c++ 中 final 修飾詞放在函式的後面,只可以是虛函式。 加final 防止子類對其進行重寫。 };
class personhong : public person // 小紅
void drinksomthing()override };
class personming : public person // 小明
這樣,就已經無意識地使用了模板方法模式。模板方法模式就是這麼簡單。
使用模板方法模式有兩點需要注意:
當然,模板方法模式也可以稍作擴充套件,下面是利用鉤子函式進行擴充套件的一種形式。
鉤子函式:
由外界條件的改變,影響到模版方法的執行,這種方法就叫做鉤子函式(hook method)。有了鉤子函式,我們就可以更靈活的控制模版方法的執行了。
模板方法可以對其進行擴充套件,在通常的情況下,我們子類是實現父類,並不能影響父類的行為,然而使用鉤子函式,我們可以讓子類影響父類的行為。
例如,一般在每次點餐前可能需要一包餐巾紙,那麼在 person 類中就需要增加選餐巾紙的行為( get*****() ),但是小明並不需要,這樣我們就需要增加乙個 bool 型別屬性,用來判斷是否需要餐巾紙,修改抽象類如下:
class person
protected:
//主食。
virtual void eatsonething() = 0;
//飲料。
virtual void drinksomthing() = 0;
bool m_need*****;
public:
void setneed*****()
virtual ~person(){};
virtual void setneed*****(bool need*****) = 0;
//開餐。
virtual void eat() // c++ 中 final 修飾詞放在函式的後嗎,只可以是虛函式。 加final 防止子類對其進行重寫。 }
};
其中 eat () 方法就是乙個模版方法,它是所有子類公共的部分**,且定義了一系列基本方法的執行順序(執行邏輯)。而 drinksomthing()、eatsonething() … 等方法便是一系列子類去實現的基本方法,例如不同的person會有不同的飲食、等等。
同樣的,小明和小紅也需要做相應的更改:
class personhong : public person //小紅
void drinksomthing()override
public:
void setneed*****(bool need*****)override };
class personming : public person // 小明
void drinksomthing()override
public:
void setneed*****(bool need*****)override
};
客戶端**設定是否需要餐巾紙:
這樣的話,我們就可以通過更改子類進而影響父類中的行為,雖然父類中的行為會隨子類而改變,然而行為的框架卻是沒有變,符合模板方法模式的定義。
模板方法模式
有這樣乙個場景 乙個演算法或流程,它的步驟以及步驟之間的順序是固定的,但具體的某一步可能有不同的實現。對於這麼乙個場景,可以建立多個類,各個類實現不同的實現,但是這樣的缺點是 易錯 難改,易錯 應為步驟和順序是固定的,而且在每個類中都要寫一遍,程式設計師怎有心情不好的時候,就有可能把其中某一步給寫錯...
模板方法模式
模板方法模式 定義乙個演算法框架,將裡面的操作步驟推遲到子類中去執行,這樣使得子類不用改變框架,只需改變某些操作步驟方法 ifndef test h define test h include include using namespace std class test virtual test v...
模板方法模式
模板方法模式 在乙個方法中定義乙個演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變演算法結構的情況下,重新定義演算法的某些步驟。還可以使用鉤子對可選部分進行判斷。include include using namespace std class caffeinebeverage ...