C++ 可配置的类工厂

时间:2023-01-02 17:37:45

  项目中常用到工厂模式,工厂模式可以把创建对象的具体细节封装到Create函数中,减少重复代码,增强可读和可维护性。传统的工厂实现如下:

 class Widget
{
public:
virtual int Init()
{
printf("Widget Init");
return ;
}
}; class WidgetA : public Widget
{
public:
virtual int Init()
{
printf("WidgetA Init");
return ;
}
}; class WidgetB : public Widget
{
public:
virtual int Init()
{
printf("WidgetB Init");
return ;
}
}; class IWidgetFactory
{
public:
virtual Widget *CreateWidget() = ;
}; class WidgetFactoryA : public IWidgetFactory
{
public:
virtual Widget *CreateWidget()
{
Widget *p = new WidgetA();
p->Init();
return p;
}
}; class WidgetFactoryB : public IWidgetFactory
{
public:
virtual Widget *CreateWidget()
{
Widget *p = new WidgetB();
p->Init();
return p;
}
}; int main()
{
IWidgetFactory *factoryA = new WidgetFactoryA();
Widget *widgetA = factoryA->CreateWidget();
IWidgetFactory *factoryB = new WidgetFactoryB();
Widget *widgetB = factoryB->CreateWidget(); return ;
}

  假设有类WidgetA,WidgetB继承自Widget,我们可以创建WidgetFactoryA和WidgetFactoryB,根据需要用factoryA对象或factoryB对象创建对应的对象。这样的方式可以满足大多数的需求。

  现在假如有这样一种需求,我们需要根据配表来生成相应的对象。比如配表中配了值1,希望生成WidgetA,值2,希望生成WidgetB。此时如果还是上述的方法,可能我们只能判断值如果为1,就用factoryA,如果为2则用factoryB。如果有WidgetA-WidgetZ,我们肯定不希望一个个用ifelse做判断。

  因此这里建立一个从type值到对象的工厂映射。只要事先注册好,就可以直接从配表读取数据,并根据type值直接创建对应的对象类型。

 class WidgetFactoryImplBase;
class WidgetFactory
{
public:
typedef std::map<int, WidgetFactoryImplBase*> FactoryImplMap;
static WidgetFactory &Instance()
{
static WidgetFactory factory;
return factory;
} void RegisterFactoryImpl(int type, WidgetFactoryImplBase *impl)
{
factory_impl_map_.insert(std::make_pair(type, impl));
}
Widget *CreateWidget(int type);
private:
FactoryImplMap factory_impl_map_;
}; class WidgetFactoryImplBase
{
public:
WidgetFactoryImplBase(int type)
{
WidgetFactory::Instance().RegisterFactoryImpl(type, this);
}
~WidgetFactoryImplBase()
{}
virtual Widget *CreateWidget() = ;
}; template<int type, class WidgetType>
class WidgetFactoryImpl : WidgetFactoryImplBase
{
public:
WidgetFactoryImpl() : WidgetFactoryImplBase(type)
{}
~WidgetFactoryImpl()
{}
virtual Widget *CreateWidget()
{
WidgetType *p = new WidgetType();
p->Init();
return p;
}
}; Widget *WidgetFactory::CreateWidget(int type)
{
auto it = factory_impl_map_.find(type);
if (it == factory_impl_map_.end()) return NULL;
return it->second->CreateWidget();
} #define DECLARE_WIDGET(type, WidgetType) \
static WidgetFactoryImpl<type, WidgetType> o_WidgetFactory_##type DECLARE_WIDGET(, Widget);
DECLARE_WIDGET(, WidgetA);
DECLARE_WIDGET(, WidgetB); int main()
{
WidgetFactory::Instance().CreateWidget();
WidgetFactory::Instance().CreateWidget();
return ;
}

  由于工厂的Create函数大同小异,首先用模板类来定义特定值对应特定对象的工厂,如果WidgetC的创建过程和一般的不一致,再创建特化类,就省去了对每个对象类写工厂类的过程。然后将这些工厂在构造时自动注册到一个总的WidgetFactory中。真正创建时只需要调用总工厂的Create函数,传入配表等传入的type值,即可创建对应的对象。

  注意这里用了一个DECLARE_WIDGET宏,来绑定type与对应的对象类型。从而将对应的创建工厂注册到总工厂中。

  此方法的逻辑简单,也很好理解,在最近的游戏活动功能中,获得了非常好的效果。由于活动的类型多达几十种,为每一种活动写工厂类和根据配表值做判断会非常繁琐,也容易出错,利用了这样的工厂注册方法后,新加一个活动类型只要加一行注册代码即可搞定,且不会出错。这里把工厂注册机制分享出来,希望对大家有所帮助。

C++ 可配置的类工厂的更多相关文章

  1. &quot&semi;检索COM类工厂中 CLSID为 &lbrace;00024500-0000-0000-C000-000000000046&rcub;的组件时失败,原因是出现以下错误&colon; 80070005&quot&semi; 问题的解决

    一.故障环境 Windows 2008 .net 3.0 二.故障描述 ​ 调用excel组件生成excel文档时页面报错.报错内容一大串,核心是"检索COM类工厂中 CLSID为 {000 ...

  2. 检索 COM 类工厂中 CLSID 为 &lbrace;000209FF-0000-0000-C000-000000000046&rcub; 的组件时失败,原因是出现以下错误&colon; 80070005

    检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005 在CSDN上总是有网友问这个 ...

  3. &lbrack;备忘&rsqb;检索 COM 类工厂中 CLSID 为 &lbrace;91493441-5A91-11CF-8700-00AA0060263B&rcub; 的组件时失败解决方法

    检索 COM 类工厂中 CLSID 为 {91493441-5A91-11CF-8700-00AA0060263B} 的组件时失败,原因是出现以下错误: 80070005 在CSDN上总是有网友问这个 ...

  4. 检索 COM 类工厂中 CLSID 解决办法

    我的服务器:windows server 2008(64位)+microsoft office 2007 企业版+windows服务应用程序 业务:调用msdn提供的SaveAsPDFandXPS.e ...

  5. 解决Office互操作错误&quot&semi;检索COML类工厂中 CLSID为 &lbrace;xxx&rcub;的组件时失败,原因是出现以下错误&colon; 80070005&quot&semi;

    Excel为例(其他如Word也适用)文件数据导入时报出以下错误: 检索COML类工厂中 CLSID为 {00024500-0000-0000-C000-000000000046}的组件时失败,原因是 ...

  6. 【原创】asp&period;net导出word 检索 COM 类工厂中 CLSID 为 &lbrace;000209FF-0000-0000-C000-000000000046&rcub; 的组件失败,原因是出现以下错误&colon; 8000401a

    我的服务器:windows server 2008(64位)+microsoft office 2007 企业版 业务:网站导出应聘word简历. 出现以下错误: 检索 COM 类工厂中 CLSID ...

  7. C&num;操作word或excel及水晶报表,检索 COM 类工厂中 CLSID 为 &lbrace;&rcub; 的组件时失败,原因是出现以下错误&colon; 80070005

    解决办法一:<转自http://www.cnblogs.com/Sue_/articles/2123372.html> 具体解决方法如下: 1:在服务器上安装office的Excel软件. ...

  8. &lpar;原创&rpar;解决Excel 互操作错误&quot&semi;检索COML类工厂中 CLSID为 &lbrace;00024500-0000-0000-C000-000000000046&rcub;的组件时失败,原因是出现以下错误&colon; 80070005&quot&semi;

    最近在.net中处理Excel文件数据导入时报出以下错误: 检索COML类工厂中 CLSID为 {00024500-0000-0000-C000-000000000046}的组件时失败,原因是出现以下 ...

  9. 索 COM 类工厂中 CLSID 为&lbrace;00024500-0000-0000-C000-000000000046&rcub; 的组件时失败,原因是出现以下错误&colon; 80070005。

    具体解决方法如下: 1:在服务器上安装office的Excel软件. 2:在"开始"->"运行"中输入dcomcnfg.exe启动"组件服务&q ...

随机推荐

  1. 1Z0-053 争议题目解析683

    1Z0-053 争议题目解析683 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 683.Your production database it functional on the ...

  2. 解决Spine骨骼混合动画错乱问题

    Spine是一个很好的制作2D骨骼动画的软件,其中提供的混合(mix)动画功能可以很柔和过度两个不同的动画,但在混合时期,稍有不善,非常容易出现各种错乱.在Spine2D骨骼动画群上,有人提出全K帧. ...

  3. SharePoint Server 2013开发之旅(三):为SharePoint Server配置App开发、部署、管理环境

    上一篇我讲解了如何利用微软提供的Office 365开发人员网站,进行在线的SharePoint App开发,这当然是不错的一个选择,因为你可以快速地进行开发和调试.(仅仅针对App开发而言).但是, ...

  4. Cygwin下载&comma;安装教程

    Cygwin是一个用于在Windows上模拟Linux环境的软件,由于工作上的需要,我要使用它,至于为什么用它,我在这里不做过多的解释,本文的目的,旨在于解决Cygwin安装上的问题. 原始的安装Cy ...

  5. scala构造器实战

    父类 abstract class Event(val name:String) { var time:Long var content:String } 子类 private[spark] clas ...

  6. UILabel 自适应大小

    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStylealloc]init]; paragraphStyle.lineB ...

  7. Java数据结构与算法&lpar;4&rpar; - ch04队列&lpar;Queue和PriorityQ&rpar;

    队列: 先进先出(FIFO). 优先级队列: 在优先级队列中,数据项按照关键字的值有序,关键字最小的数据项总在对头,数据项插入的时候会按照顺序插入到合适的位置以确保队列的顺序,从后往前将小于插入项的数 ...

  8. Sersync同步过滤&period;svn文件夹

    Sersync同步过滤.svn文件夹 <filter start="true"> <exclude expression="(.*).svn(.*)&q ...

  9. selenium元素定位大全

    要做自动化,首先要了解页面结构,要了解页面结构,就要了解页面元素的定位方法 在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合B ...

  10. windows Jenkins git 配置

    待更新 插件下载地址:http://updates.jenkins-ci.org/download/plugins/ 参考地址:https://blog.csdn.net/zzy1078689276/ ...