c++对象工厂
一.简单工厂
#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++对象工厂的更多相关文章
- struts2的对象工厂(ObjectFactory)
ObjectFactory,是xwork中很重要的一个类,是产生action的地方.单独使用xwork的时候,action都是这个类创建的.struts2包装了ObjectFactory,自成了一个S ...
- Mybatis框架基础支持层——反射工具箱之对象工厂ObjectFactory&DefaultObjectFactory(5)
ObjectFactory官方简介:MyBatis每次创建结果集对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成. 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认 ...
- Javascript我学之六对象工厂函数与构造函数
本文是金旭亮老师网易云课堂的课程笔记,记录下来,以供备忘. 概述 使用对象字面量,或者向空对象中动态地添加新成员,是最简单易用的对象创建方法. 然而,除了这两种常用的对象创建方式,JavaScript ...
- js对象工厂函数与构造函数
转自:http://www.cnblogs.com/Jener/p/5920963.html ★概述: 使用对象字面量,或者向空对象中动态地添加新成员,是最简单易用的对象创建方法.然而 ...
- 第四章 Spring.Net 如何管理您的类___对象、对象工厂和应用程序上下文
在前面一章我们介绍了依赖注入,控制反转的概念,以及自己动手搭建了一下Spring.Net的环境.通过这些操作,我们知道了Spring.Net 的核心是使用依赖注入或控制反转这种思想来管理业务对象,降低 ...
- JS构造函数、对象工厂、原型模式
1.对象创建的3中方法 1.1.对象字面量 var obj = { name: "mingzi", work: function () { console.log("wo ...
- MyBatis配置文件(五)--objectFactory对象工厂
我们在使用MyBatis执行查询语句的时候,通常都会有一个返回类型,这个是在mapper文件中给sql增加一个resultType(或resultMap)属性进行控制.resultType和resul ...
- Objective-C设计模式——工厂方法模式virtual constructor(对象创建)
工厂方法模式 工厂方法模式可以控制对象的创建过程,屏蔽对象创建的细节,可以直接创建出我们所需要的已经配置好的对象. 工厂方法模式定义了创建方法的接口,让子类决定实例化哪一个类,工厂方法模式使得一个类的 ...
- 面向对象+闭包+三种对象的声明方式(字面式、new Object、构造函数、工厂模式、原型模式、混合模式)
面向对象: 对代码的一种抽象,对外统一提供调用接口的编程思想 对象的属性:事物自身拥有的东西 对象的方法:事物的功能 对象:事物的一个实例 对象的原型:.prototype -> 内存地址 -& ...
随机推荐
- MyEclipse中如何配置默认jsp为UTF-8格式
- Android TimeAnimator
TimeAnimator:提供了一个简单的回调机制,通过 TimeAnimator.TimeListener,在动画的每一帧处通知你.这个动画器没有时间,插值或是对象值设定.回调监听器为每一帧动画接受 ...
- 如何用Python写一个贪吃蛇AI
前言 这两天在网上看到一张让人涨姿势的图片,图片中展示的是贪吃蛇游戏, 估计大部分人都玩过.但如果仅仅是贪吃蛇游戏,那么它就没有什么让人涨姿势的地方了. 问题的关键在于,图片中的贪吃蛇真的很贪吃XD, ...
- 搭建ssh框架项目(五)
一.控制层优化 (1)创建BaseAction.java类 package com.cppdy.ssh.web.action; import javax.servlet.http.HttpServle ...
- PHP将数据写入指定文件中
首先创建一个空的txt文件,这里我们创建了一个1.txt的空文件. 第一种方法:fwrite函数 <?php $file=fopen('1.txt','rb+'); var_dump(fwrit ...
- python+selenium+unittest 实现自动化测试
示例代码: baidu.py import csv #导入csv模块 from itertools import islice #从itertools导入islice,后边让其默认跳过第一行使用 fr ...
- 浅析微信支付:公众平台卡券功能开通、HTML5线上发券(JS-SDK接口)、查看卡券详情
本文是[浅析微信支付]系列文章的第十六篇,主要讲解如何使用微信公众平台的卡券功能.如何使用HTML5在网页展示用户领券以及微信卡券和商户平台代金券的关系. 浅析微信支付系列已经更新十六篇了哟-,没有看 ...
- POJ 1631 Bridging signals (LIS:最长上升子序列)
题意:给你一个长为n(n<=40000)的整数序列, 要你求出该序列的最长上升子序列LIS. 思路:要求(nlogn)解法 令g[i]==x表示当前遍历到的长度为i的所有最长上升子序列中的最小序 ...
- 【Java】 剑指offer(50-2) 字符流中第一个只出现一次的字符
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字 ...
- Android 之 tools:context和tools:ignore两个属性的作用
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= ...