一.简单工厂

#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. 在chrome开发者工具中观察函数调用栈、作用域链与闭包

    在chrome开发者工具中观察函数调用栈.作用域链与闭包 在chrome的开发者工具中,通过断点调试,我们能够非常方便的一步一步的观察JavaScript的执行过程,直观感知函数调用栈,作用域链,变量 ...

  2. OCM_第十六天课程:Section7 —》GI 及 ASM 安装配置 _安装 GRID 软件/创建和管理 ASM 磁盘组/创建和管理 ASM 实例

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  3. cf 1041C双指针

    比赛的时候想着用单调队列做... 打完发现其实就是个双指针 /* 构造双指针解决即可 */ #include<iostream> #include<cstring> #incl ...

  4. 将eclipse的maven项目导入到intellij idea中

    最近项目中需要用到idea,需要将原来的eclipse项目进行转移.捣鼓了半天终于成功了,在这里和大家分享下,希望对大家有所帮助,如有错误,欢迎指正. idea的确是一款很智能的开发工具,真的是爱不释 ...

  5. 判断上学和放假的demo

    var today = new Date(); var xq = today.getDay(); var Now = today.getHours(); if (xq >= 1 &&am ...

  6. python算法双指针问题:二分查找

    这里要注意的是//向下取整,下次循环时,如果大于查找的数字,start+1. 并且,只能向下取整,如果向上取整. 那么,在比较第一个数时,start = 0 .end = 1.mid = 1.就会进入 ...

  7. BZOJ3377 [Usaco2004 Open]The Cow Lineup 奶牛序列 其他

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3377 题意概括 给出一个序列,序列中的数字为1~k中的. 让你求最短的非子序列长度. 题解 我们把 ...

  8. 【Java】 剑指offer(9) 斐波那契数列及青蛙跳台阶问题

     本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项 ...

  9. 【Java】 剑指offer(44) 连续子数组的最大和

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 数字以0123456789101112131415…的格式序列化到 ...

  10. post请求测试代码

    public class TestResourceCommentRestController { private final static String API_URI_DEBUG = "h ...