一.简单工厂

#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. favicon.ico问题

    在访问web的时候,有时出现favicon.ico 不知道这是一个什么东西,查看百度:

  2. ADC自动转接功能Lua实现

    一.背景介绍: 虽然使用Mod_fifo和mod_callcenter可以做呼叫中心的应用,但在实现应用中,这两个模块很难客制化需求,再此我用Lua实现了5路客服(1000-1004),一个呼叫中心号 ...

  3. 今天刚用asp.net做的导出Eecel

    protected void daochu_Click(object sender, EventArgs e)        {                string hql = "s ...

  4. CopyPropertis

    commons-beanutils.jar PropertyUtils.copyProperties(Object dest, Object orig) spring-beans.jar BeanUt ...

  5. Pandas详解一

    pandas简介 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的.Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具.pandas提 ...

  6. Java中BigDecimal类介绍及用法

    Java中提供了大数字(超过16位有效位)的操作类,即 java.math.BinInteger 类和 java.math.BigDecimal 类,用于高精度计算. 其中 BigInteger 类是 ...

  7. codeforce 139E

    成段更新+离散化才能过,数据好强.. 单点更新挂在了test27,下次做到成段更新再来做! /* 期望=存活概率*点权值/100 ans=sum(期望) 离散化树木权值,数轴统计累加可能倒下的树木概率 ...

  8. 基于struts研究传值问题

    一.新建项目 struts 1.file——>new——>Web Project——>取名struts——>finsh——>将之前项目下的jar包copy到该项目下 2. ...

  9. python 全栈开发,Day19(组合,组合实例,初识面向对象小结,初识继承)

    一.组合 表示的一种什么有什么的关系 先来说一下,__init__的作用 class Dog: def __init__(self, name, kind, hp, ad): self.name = ...

  10. Thread + 匿名内部类

    package chapter01; public class MyThread01 extends Thread{ @Override public void run() { //让当前线程执行的代 ...