一.简单工厂

#pragma once

struct 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++对象工厂的更多相关文章

  1. struts2的对象工厂(ObjectFactory)

    ObjectFactory,是xwork中很重要的一个类,是产生action的地方.单独使用xwork的时候,action都是这个类创建的.struts2包装了ObjectFactory,自成了一个S ...

  2. Mybatis框架基础支持层——反射工具箱之对象工厂ObjectFactory&DefaultObjectFactory(5)

    ObjectFactory官方简介:MyBatis每次创建结果集对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成. 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认 ...

  3. Javascript我学之六对象工厂函数与构造函数

    本文是金旭亮老师网易云课堂的课程笔记,记录下来,以供备忘. 概述 使用对象字面量,或者向空对象中动态地添加新成员,是最简单易用的对象创建方法. 然而,除了这两种常用的对象创建方式,JavaScript ...

  4. js对象工厂函数与构造函数

    转自:http://www.cnblogs.com/Jener/p/5920963.html ★概述:         使用对象字面量,或者向空对象中动态地添加新成员,是最简单易用的对象创建方法.然而 ...

  5. 第四章 Spring.Net 如何管理您的类___对象、对象工厂和应用程序上下文

    在前面一章我们介绍了依赖注入,控制反转的概念,以及自己动手搭建了一下Spring.Net的环境.通过这些操作,我们知道了Spring.Net 的核心是使用依赖注入或控制反转这种思想来管理业务对象,降低 ...

  6. JS构造函数、对象工厂、原型模式

    1.对象创建的3中方法 1.1.对象字面量 var obj = { name: "mingzi", work: function () { console.log("wo ...

  7. MyBatis配置文件(五)--objectFactory对象工厂

    我们在使用MyBatis执行查询语句的时候,通常都会有一个返回类型,这个是在mapper文件中给sql增加一个resultType(或resultMap)属性进行控制.resultType和resul ...

  8. Objective-C设计模式——工厂方法模式virtual constructor(对象创建)

    工厂方法模式 工厂方法模式可以控制对象的创建过程,屏蔽对象创建的细节,可以直接创建出我们所需要的已经配置好的对象. 工厂方法模式定义了创建方法的接口,让子类决定实例化哪一个类,工厂方法模式使得一个类的 ...

  9. 面向对象+闭包+三种对象的声明方式(字面式、new Object、构造函数、工厂模式、原型模式、混合模式)

    面向对象: 对代码的一种抽象,对外统一提供调用接口的编程思想 对象的属性:事物自身拥有的东西 对象的方法:事物的功能 对象:事物的一个实例 对象的原型:.prototype -> 内存地址 -& ...

随机推荐

  1. tomcat6和tomcat7管理用户manager配置

    tomcat用户登录文件配置 如果想要对部署在tomcat上的项目进行管理查看,需要在tomcat安装目录conf文件夹下的tomcat-user.xml里添加用户登录权限.具体添加的内容如下: To ...

  2. jmeter之ip欺骗

    说明:我看有的博客说官方文档是在jmeter2.5以上的版本有此功能的实现~ 我的是2.13版本,也可以实现 . 准备工作: 使用IP欺骗功能必须得本地有多个可用IP,通常普通的PC机只有一个物理网卡 ...

  3. GitHub上优秀的Go开源项目

    近一年来,学习和研究Go语言,断断续续的收集了一些比较优秀的开源项目,这些项目都非常不错,可以供我们学习和研究Go用,从中可以学到很多关于Go的使用.技巧以及相关工具和方法.我把他们整理发出来,大家有 ...

  4. 错误代码 1045 Access denied for user 'root'@'localhost' (using password:YES)

    1 前言 现象是用MySQL 5.7 Command Line Client可以使用root账号进入,但是其它navicat,phpsqladmin,mysql workbench,heidisql用 ...

  5. mysql语句判断是否存在记录,没有则插入新纪录否则不执行

    1 前言 由于项目需要,当某个表如果有记录,就不执行加入语句,否则加入新纪录(测试数据).思路是:判断表的记录是否为空,然后再决定是否插入 2 代码 DROP PROCEDURE IF EXISTS ...

  6. JavaScript的类型自动转换样例集合处

    1.前言 如果Javascript期望使用一个字符串,它会把给定的值转换成字符串:如果Javascript期望使用一个数字,它会把给定的值转化成数字. 2.样例 2.1.字符串拼接时有数字 windo ...

  7. vue-swiper的使用

    写博客不是我的爱好,只是人脑毕竟空间只有那么大,有时候会忘了,好记性不如烂笔头,所以通过博客记录点点滴滴,以后可以翻出来看. vue-awesome-swiper官网链接https://www.npm ...

  8. 《剑指offer》-左旋转字符串

    汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S="abc ...

  9. 安装elasticsearch-7.0.0及插件

    下载安装包:(下载地址:https://www.elastic.co/cn/downloads/elasticsearch)elasticsearch-7.0.0-linux-x86_64.tar.g ...

  10. 037 对于HIVE架构的理解

    0.发展 在hive公布源代码之后 公司又公布了presto,这个比较快,是基于内存的. impala:3s处理1PB数据. 1.Hive  能做什么,与 MapReduce 相比优势在哪里 关于hi ...