C++設計模式之模板方法模式
前言
離開了自己工作了將近兩年的公司,日子不再有了忙碌,可以閑下來,躺在家里的床上,想著以后的路怎么走,說實話,真的很迷茫,從2012年畢業(yè)到現(xiàn)在,時間不長,但是學到的東西真的是非常有限,一直從事于Windows平臺上的開發(fā)。說到Windows平臺的開發(fā),大家都肯定知道的HOOK的,即使不知道HOOK,對于COM應該也是知道的,我的系列博文中也對COM進行過全面的總結。說白了,HOOK就是在執(zhí)行某個功能時,會有一個一系列的執(zhí)行過程,對于這個過程一般都是固定的,比如:第一步執(zhí)行什么,第二步干什么,最后一步干什么,都是設計好的。而具體如何去完成每一步,都是可以由程序員去控制的。COM也是如此,COM是面對接口的,當完成某一個功能模塊時,就可能是系列接口的疊加調(diào)用,而接口的實現(xiàn)都是由程序員來控制的。說白了,一個功能模塊的實現(xiàn)流程是固定了,但是對于每一步的具體實現(xiàn)都是不固定的。對于這種需求,一般是如何來做的呢?從設計模式的角度來說,這個設計模式叫模板方法模式,可能你不知道這個設計模式的名字,但是,這種方法你已經(jīng)用過了?,F(xiàn)在我就對模板方法模式進行詳細的總結。
模板方法模式
在GOF的《設計模式:可復用面向?qū)ο筌浖幕A》一書中對模板方法模式是這樣說的:定義一個操作中的算法骨架,而將一些步驟延遲到子類中。TemplateMethod使得子類可以不改變一個算法的接口即可重定義改算法的某些特定步驟。
我結合我在實際開發(fā)項目中的一個例子來說說這個模板方法模式吧。我們曾經(jīng)做過一款產(chǎn)品,這個產(chǎn)品類似于一個云端的文件管理客戶端。對于這樣的一個客戶端,由于其云端的服務器有三種,而每一種服務器之間的通信方式和對外公開的接口都是不是一致的,這就需要實現(xiàn)的客戶端要屏蔽云端服務器和接口的差異性,而提供統(tǒng)一的操作界面,所以在實現(xiàn)這個客戶端的同時,我們實現(xiàn)了一個框架,一個對于服務器和接口是通用的框架,比如就拿文件下載來說說。我們的實現(xiàn)大概如下:
class FileOperation
{
public:
bool DownloadFile(wchar_t *pSrc, wchar_t *pDest)
{
if (!pSrc || !pDest) return false;
if (!DoBeginDownloadFile(pSrc, pDest)) return false;
if (!DoDownloadFile(pSrc, pDest)) return false;
if (!DoEndDownloadFile(pSrc, pDest)) return false;
}
protected:
virtual bool DoBeginDownloadFile(wchar_t *pSrc, wchar_t *pDest);
virtual bool DoDownloadFile(wchar_t *pSrc, wchar_t *pDest);
virtual bool DoEndDownloadFile(wchar_t *pSrc, wchar_t *pDest);
};
class HttpFileOperation : public FileOperation
{
protected:
virtual bool DoBeginDownloadFile(wchar_t *pSrc, wchar_t *pDest);
virtual bool DoDownloadFile(wchar_t *pSrc, wchar_t *pDest);
virtual bool DoEndDownloadFile(wchar_t *pSrc, wchar_t *pDest);
};
class SOAPFileOperation : public FileOperation
{
protected:
virtual bool DoBeginDownloadFile(wchar_t *pSrc, wchar_t *pDest);
virtual bool DoDownloadFile(wchar_t *pSrc, wchar_t *pDest);
virtual bool DoEndDownloadFile(wchar_t *pSrc, wchar_t *pDest);
};
下載文件的流程為:先調(diào)用DoBeginDownloadFile,執(zhí)行下載文件之前的一些操作,再調(diào)用DoDownloadFile實現(xiàn)真正的文件下載,最后調(diào)用DoEndDownloadFile完成文件下載的清理工作。對于任何服務器,下載文件的這個流程是不會發(fā)生變化的。而在DoBeginDownloadFile、DoDownloadFile和DoEndDownloadFile的內(nèi)部具體是如何實現(xiàn)的,由程序員根據(jù)具體的云端服務器和對外公開的接口來完成的。最終客戶端去完成文件下載操作時,只會調(diào)用DownloadFile函數(shù)就可以完成??梢钥吹?,在上面的代碼中,只有DownloadFile是public的,其它的操作函數(shù)都是protected。這也意味著,我們完成的框架對外只公開DownloadFile接口。
UML類圖
AbstractClass(抽象類):定義抽象的原語操作,具體的子類將重定義它們以實現(xiàn)一個算法的各步驟。主要是實現(xiàn)一個模板方法,定義一個算法的骨架。該模板方法不僅調(diào)用原語操作,也調(diào)用定義在AbstractClass或其他對象中的操作。
ConcreteClass(具體類):實現(xiàn)原語操作以完成算法中與特定子類相關的步驟。
由于在具體的子類ConcreteClass中重定義了實現(xiàn)一個算法的各步驟,而對于不變的算法流程則在AbstractClass的TemplateMethod中完成。
使用場合
模板方法是一種代碼復用的基本技術。它們在類庫中尤為重要,它們提取了類庫中的公共行為。在使用模板方法時,很重要的一點是模板方法應該指明哪些操作是可以被重定義的,以及哪些是必須被重定義的。要有效的重用一個抽象類,子類編寫者必須明確了解哪些操作是設計為有待重定義的。
代碼實現(xiàn)
這里就根據(jù)上面的類圖,對模板方法模式進行了簡單的實現(xiàn)。由于該模式非常簡單,所以也沒有更多的可以講的了。
#include <iostream>
using namespace std;
class AbstractClass
{
public:
void TemplateMethod()
{
PrimitiveOperation1();
cout<<"TemplateMethod"<<endl;
PrimitiveOperation2();
}
protected:
virtual void PrimitiveOperation1()
{
cout<<"Default Operation1"<<endl;
}
virtual void PrimitiveOperation2()
{
cout<<"Default Operation2"<<endl;
}
};
class ConcreteClassA : public AbstractClass
{
protected:
virtual void PrimitiveOperation1()
{
cout<<"ConcreteA Operation1"<<endl;
}
virtual void PrimitiveOperation2()
{
cout<<"ConcreteA Operation2"<<endl;
}
};
class ConcreteClassB : public AbstractClass
{
protected:
virtual void PrimitiveOperation1()
{
cout<<"ConcreteB Operation1"<<endl;
}
virtual void PrimitiveOperation2()
{
cout<<"ConcreteB Operation2"<<endl;
}
};
int main()
{
AbstractClass *pAbstractA = new ConcreteClassA;
pAbstractA->TemplateMethod();
AbstractClass *pAbstractB = new ConcreteClassB;
pAbstractB->TemplateMethod();
if (pAbstractA) delete pAbstractA;
if (pAbstractB) delete pAbstractB;
}
總結
模板方法模式,總的來說很好接受,很好理解,沒有難點;對于此設計模式,我個人覺的還是可以和裝飾模式進行對比一下。還是有一些相似之處的。好了,該設計模式的講解就到此結束。
相關文章
VC++中HTControl控件類的CHTSlider控制桿控件類簡介
這篇文章主要介紹了VC++中HTControl控件類的CHTSlider控制桿控件類,需要的朋友可以參考下2014-08-08VS2022創(chuàng)建Windows服務程序的方法步驟
本文主要介紹了VS2022創(chuàng)建Windows服務程序的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-05-05Cocos2d-x中獲取系統(tǒng)時間和隨機數(shù)實例
這篇文章主要介紹了Cocos2d-x中獲取系統(tǒng)時間和隨機數(shù)實例,本文代碼含有大量注釋來講解獲取系統(tǒng)時間和隨機數(shù)的方法,需要的朋友可以參考下2014-09-09