#include <map>
#include <string>
#include <cassert>
#include <typeinfo>
#include "LokiTypeInfo.h"
using std::map;
using std::string;
using std::type_info;
using namespace Loki;
/*
备注,此处的对象工厂以及克隆工厂只是为了阐述原理,不具有实际意义,
实际中使用,难免在Create函数中传入参数,详见Loki
*/
//对象工厂
template
<
typename TBaseClassType, //最底层基类类型
typename TIdentify, //类的标识符
typename TCreate = TBaseClassType* (*) () //类对象的生成函数
>
class CFactory
{
public:
//注册
const bool Register(const TIdentify& tIdC, TCreate tCreate)
{
return mapAssociate.insert(std::make_pair(tIdC, tCreate)).second;
}
//注销
const bool Unregister(const TIdentify& tIdC)
{
return 1 == mapAssociate.erase(tIdC);
}
//创建
TBaseClassType* Create(const TIdentify& tIdC)
{
auto it = mapAssociate.find(tIdC);
if (it != mapAssociate.end())
{
return (it->second)();
}
/*
若有需要,此处可以以 policy-based class 方式设计,
让CFactory以public方式继承一个错误处理基类
*/
return nullptr;
}
private:
map<TIdentify, TCreate> mapAssociate;
};
//克隆工厂
template
<
typename TBaseClassType, //最底层基类类型
typename TCreate =
TBaseClassType* (*) (const TBaseClassType*) //类对象的生成函数
>
class CCloneFactory
{
public:
const bool Register(const TypeInfo& tTemC, TCreate tCreate)
{
return mapAssociate.insert(std::make_pair(tTemC, tCreate)).second;
}
const bool Unregister(const TypeInfo& typeInfoC)
{
return 1 == mapAssociate.erase(typeInfoC);
}
TBaseClassType* Create(const TBaseClassType* pObjectC)
{
if (pObjectC == nullptr)
{
return nullptr;
}
auto it = mapAssociate.find(typeid(*pObjectC));
if (it != mapAssociate.end())
{
return (it->second)(pObjectC);
}
return nullptr;
}
private:
map<TypeInfo, TCreate> mapAssociate; //TypeInfo来自Loki
/*
type_info::name()返回的结果只适合调试,无法保证此字符串就是实际类名称,
并且无法保证这个字符串在整个程序中是独一无二的,不同的类可能返回相同字符串,
所以这里不能用type_info::name()代表的字符串充当key
此处的Key必须具备RTTI特性,否则毫无用处
*/
};
class CFather
{
public:
CFather() : nV0(0) {}
virtual ~CFather(){}
public:
int nV0;
};
class CChild0 : public CFather
{
public:
CChild0() { nV0 = 1; }
};
class CChild1 : public CFather
{
public:
CChild1() { nV0 = 2; }
};
template<typename T, typename TBase>
TBase* CreateTest()
{
return new T;
}
template<typename T, typename TBase>
TBase* CloneTest(const TBase* pTemC)
{
return new T(static_cast<const T&>(*pTemC));
}
int main()
{
CFactory<CFather, string> Factor;
Factor.Register(string("Father"), CreateTest<CFather, CFather>);
Factor.Register(string("Child0"), CreateTest<CChild0, CFather>);
Factor.Register(string("Child1"), CreateTest<CChild1, CFather>);
int aValue[] =
{
Factor.Create("Father")->nV0, //0
Factor.Create("Child0")->nV0, //1
Factor.Create("Child1")->nV0 //2
};
CCloneFactory<CFather> CloneFactory;
CloneFactory.Register(typeid(CFather), CloneTest<CFather, CFather>);
CloneFactory.Register(typeid(CChild0), CloneTest<CChild0, CFather>);
CloneFactory.Register(typeid(CChild1), CloneTest<CChild1, CFather>);
CFather* pChild1 = new CChild1;
int nTem = CloneFactory.Create(pChild1)->nV0; //nTem = 2
return 0;
}
第八章 对象工厂
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 今天我们来讨论创建对象的几种方式,按照以下几种方式进行介绍: (1)工厂模式 (2)构造函数模式 (3)原型模式 ...
- 面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法。这样我们如果把一些属性及方法封装起来,日后使用将非...