日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++对象工厂

發布時間:2024/4/11 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++对象工厂 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.簡單工廠

#pragma oncestruct IObjectA {virtual void Test1()=0; };class ObjectA:public IObjectA { public:virtual void Test1(){} };struct IObjectB {virtual void Test2()=0; };class ObjectB:public IObjectB { public:virtual void Test2(){} };class ObjectFactory { public:static void Create(int nFlag,void** ppVoid){switch (nFlag){case 1:{IObjectA *pA=new ObjectA;*ppVoid=pA;}break;case 2:{IObjectB *pB=new ObjectB;*ppVoid=pB;}break;}} };class ObjectTest { public:ObjectTest();~ObjectTest();static void Test1(){IObjectA *pA=nullptr;ObjectFactory::Create(1,(void**)&pA);pA->Test1();} };

優缺點:這種工廠適用于對象不多的情況下,否則工廠類必須要知道所有類

對于一個比較大的項目如果有較多的對象就不適合了

二.使用__uuidof簡化類型創建

借助這個關鍵字,可以為一個類指定一個guid

[uuid("F5844C2A-50D1-4F2C-85DB-429729927F0F") ] struct IObjectA {virtual void Test1()=0; };

如下代碼:

template<typename T>static T* Create(){GUID id=__uuidof(T);if(IsEqualGUID(id,__uuidof(IObjectA))){IObjectA *pA=new ObjectA;return (T*)pA;} else if(IsEqualGUID(id,__uuidof(IObjectB))){IObjectB *pB=new ObjectB;return (T*)pB;}return nullptr;}static void Test2(){IObjectA *pA=ObjectFactory::Create<IObjectA>();pA->Test1();}

以上的使用方式對外確實便利了很多

下面來解決if else的問題,

三.使用map來存儲

1.由于map要使用guid來作為key,那么就需要一個比較函數

來看一下IsEqualGUID的實現,實際是一個宏,對字符串的比較

__inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2) {return !memcmp(&rguid1, &rguid2, sizeof(GUID)); }

2.為了可以靈活創建對象,我們可以使用函數指針來創建對象

基于以上2點,我們創建來以下數據結構

typedef void (*CreateFunc)(void** ppVoid);struct guidCompare{bool operator () (GUID rguid1,GUID rguid2) const{return memcmp(&rguid1, &rguid2, sizeof(GUID))< 0;}};static std::map<GUID,CreateFunc,guidCompare> m_mapObj;

接著要初始化各個對象的創建函數

template<typename T,typename I>static void CreateInstance(void** ppVoid){I *pObject=new T;*ppVoid=pObject;}static void Init(){m_mapObj.insert(std::map<GUID,CreateFunc>::value_type(__uuidof(IObjectA),CreateInstance<ObjectA,IObjectA>));m_mapObj.insert(std::map<GUID,CreateFunc>::value_type(__uuidof(IObjectB),CreateInstance<ObjectB,IObjectB>));}

3.再次改造一個Create方法

template<typename T>static T* CreateFromMap(){GUID id=__uuidof(T);std::map<GUID,CreateFunc>::iterator iter=m_mapObj.find(id);if(iter!=m_mapObj.end()){T* pObject=NULL;iter->second((void**)&pObject);return pObject;}return nullptr;}

4.測試代碼

static void Test3(){ObjectFactory::Init();IObjectA *pA=ObjectFactory::CreateFromMap<IObjectA>();pA->Test1();}

以上步驟不再用一個一個的判斷對象的guid,唯一的問題點在于初始化的問題

四.借助全局對象初始化來注冊

封裝一個Register方法

template<typename T,typename I>static void Register(){m_mapObj.insert(std::map<GUID,CreateFunc>::value_type(__uuidof(I),CreateInstance<T,I>));}Register<ObjectA,IObjectA>();

如果直接全局來調用這個方法的話顯的有些暴力,而且容易出錯,重復注冊,可以借助一個輔助類在構造函數內完成

class ObjectACreateHelper{public:ObjectACreateHelper(){ObjectFactory::Register<ObjectA,IObjectA>();}};class ObjectBCreateHelper{public:ObjectBCreateHelper(){ObjectFactory::Register<ObjectB,IObjectB>();}};ObjectACreateHelper g_ObjectACreateHelper;ObjectBCreateHelper g_ObjectBCreateHelper;

上面的代碼就完成的差不多了,上面的代碼就是力氣活來,可以再想辦法簡化

五.使用宏和模板來簡化注冊

template<typename T,typename I> class CObjectCreateHelper { public:CObjectCreateHelper(){ObjectFactory::Register<T,I>();} };#define REG_CREATEObject(T, I) CObjectCreateHelper<T,I> g_##T;REG_CREATEObject(ObjectA,IObjectA) REG_CREATEObject(ObjectB,IObjectB)

現在就全部完成了整個步驟的改造,此思想可以用到很多類似的對象創建方法,很管用

總結

以上是生活随笔為你收集整理的c++对象工厂的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。