一、概念
定義一個操作中的算法的骨架(穩定),而將一些步驟延遲定義一個虛函數,讓子類去實現(重寫)這個虛函數>(變化)到子類<支持子類來變化,我現在定不下來如何實現,讓子類來實現>中。Template Method使得子類可以不改變(複用)一個算法的結構即可重定義(override重寫)該算法的某些特定步驟——《設計模式》GOF
二、動機
在軟件構建過程中,對於某一項任務,它常常有穩定的整體操作結構,但各個子步驟卻有很多改變的需求,或者由於固有的原因(比如框架與應用之間的關係)而無法和任務的整體結構同時實現(必有一個早一個晚)。如何在確定穩定操作結構的前提下,來靈活應對各個子步驟的變化或者晚期實現需求?
三、源代碼講解
應用開發人員實現了部分應用程序步驟開發和程序的整體流程。而這個流程既要調用到類庫開發人員寫的方法step1,step3,step5,同時還需要調用到應用程序開發人員(自己或協作者)寫的step2,step4方法。整體流程應該由框架設計人員爲我們設定好,常常不需要我們更改,而且是穩定的。
//程序庫開發人員
class Library{
public:
void Step1(){
//...
}
void Step3(){
//...
}
void Step5(){
//...
}
};
//應用程序開發人員
class Application{
public:
bool Step2(){
//...
}
void Step4(){
//...
}
};
int main()
{
Library lib();
Application app();
lib.Step1();
if (app.Step2()){
lib.Step3();
}
for (int i = 0; i < 4; i++){
app.Step4();
}
lib.Step5();
}
四、使用模板方法進行改進
//程序庫開發人員
class Library {
public:
// 穩定 template method
void Run() {
Step1();
if (Step2()) { // 支持變化 => 虛函數的多態調用
Step3();
}
for (int i = 0; i < 4; i++) {
Step4(); // 支持變化 => 虛函數的多態調用
}
Step5();
}
virtual ~Library() { }
protected:
// 穩定
void Step1() {
// .....
}
// 穩定
void Step3() {
// .....
}
// 穩定
void Step5() {
// .....
}
virtual bool Step2() = 0; // 變化
virtual void Step4() = 0; // 變化
};
//應用程序開發人員
class Application : public Library {
protected:
virtual bool Step2(){
// 子類重寫實現
}
virtual void Step4() {
// 子類重寫實現
}
};
int main() {
// 多態指針
Library* pLib=new Application();
lib->Run();
// 注意上面,我們是使用的虛析構函數,是有必要的,若是不寫成虛析構函數,
// 我們就調用不了子類的析構函數,有可能出錯,所以任何基類我們都應該寫出析構函數,而且是虛析構函數
delete pLib;
}
五、類圖結構
六、要點總結
-
Template Mechod模式是一種非常基礎性的設計模式,在面向對象系統中有着大量的應用。它用最簡潔的機制(虛函數的多態性)爲很多應用程序框架提供了靈活的拓展點,是代碼複用方面的基本實現結構。
-
除了可以靈活應對子步驟的變化外,“不要調用我,讓我來調用你<晚綁定>”的反向控制結構是Template Method的典型應用。
-
在具體實現方面,被Template Method調用的虛方法可以具有實現,也可以沒有任何實現(抽象方法、純虛方法),但一般推薦將它們設置爲protected方法<單獨作爲一個方法暴露出去給人家調用時沒有意義的,他往往放在一個流程中,纔有意義>。
七、應用場景
-
具有統一的操作步驟或操作過程。
-
具有不同的操作細節。
-
存在多個具有同樣操作步驟的有場景,但某些具體的操作細節卻各不相同。