一般的工厂模式的产品类都继承同一个基类,我们假设这个基类现在是
#pragma once
class CBaseTest
{
public:
CBaseTest(void) {}
virtual ~CBaseTest(void) {}
public:
virtual void FunOne() = 0;
virtual void FunTwo() = 0;
virtual void FunThree() = 0;
};
然后生成多个派生类,如下
#pragma once
#include "BaseTest.h"
class CTestA : public CBaseTest
{
public:
CTestA(void);
~CTestA(void);
public:
virtual void FunOne();
virtual void FunTwo();
virtual void FunThree();
};
#include "StdAfx.h"
#include "TestA.h"
#include <iostream>
using namespace std;
CTestA::CTestA(void)
{
}
CTestA::~CTestA(void)
{
}
void CTestA::FunOne()
{
cout << "CTestA::FunOne" << endl;
}
void CTestA::FunTwo()
{
cout << "CTestA::FunTwo" << endl;
}
void CTestA::FunThree()
{
cout << "CTestA::FunThree" << endl;
}
在加个子类
#pragma once
#include "BaseTest.h"
class CTestB : public CBaseTest
{
public:
CTestB(void);
~CTestB(void);
public:
virtual void FunOne();
virtual void FunTwo();
virtual void FunThree();
};
#include "StdAfx.h"
#include "TestB.h"
#include <iostream>
using namespace std;
CTestB::CTestB(void)
{
}
CTestB::~CTestB(void)
{
}
void CTestB::FunOne()
{
cout << "CTestB::FunOne" << endl;
}
void CTestB::FunTwo()
{
cout << "CTestB::FunTwo" << endl;
}
void CTestB::FunThree()
{
cout << "CTestB::FunThree" << endl;
}
然后我们增加一个工厂类
class Factory
{
public:
Factory(){}
~Factory(){}
public:
CBaseTest *CreateObject(string strName)
{
CBaseTest *pReturn = NULL;
if(strName == "CTestA")
{
pReturn = new CTestA();
}
else if(strName == "CTestB")
{
pReturn = new CTestB();
}
}
}
这个类很简单的根据传入的字符串创建相应的对象返回给使用者,但是这有个问题就是每次增加了一个子类,就需要修改这个工厂类,这样我觉得很麻烦,后面我想能不能根据传入的字符串动态的创建对象呢,C++语言是不支持这种方式的,但是如果使用MFC那一套机制是可以做到的,所以我们模仿下MFC那套
我们先定义几个宏,宏的定义如下
#ifndef _COMMON_H
#define _COMMON_H
// 创建对象函数指针定义
typedef void *(* PCreateObject)();
struct CRuntimeClass
{
char *m_lpszClassName; // 类的名字
PCreateObject m_pfnCreateObject; // 创建对象函数指针
CRuntimeClass *m_pNextClass; // 该类的下一个类
static CRuntimeClass *pFirstClass; // 头指针
};
struct AFX_CLASSINIT
{
AFX_CLASSINIT(CRuntimeClass *pNewClass);
};
#define DECLARE_DYNCREATE(class_name) \
public: \
static CRuntimeClass class##class_name; \
static void *CreateObject();
#define IMPLEMENT_DYNCREATE(class_name) \
void *class_name::CreateObject(){return new class_name();} \
static char _lpsz##class_name[] = #class_name; \
CRuntimeClass class_name::class##class_name = \
{ _lpsz##class_name, class_name::CreateObject, NULL}; \
static AFX_CLASSINIT _init_##class_name(&class_name::class##class_name);
#endif
这是实现文件的源码
#include "stdafx.h"
#include "Common.h"
AFX_CLASSINIT::AFX_CLASSINIT(CRuntimeClass *pNewClass)
{
pNewClass->m_pNextClass = CRuntimeClass::pFirstClass;
CRuntimeClass::pFirstClass = pNewClass;
}
CRuntimeClass *CRuntimeClass::pFirstClass = NULL;
这其实跟MFC的处理是差不多的,只不过是简化了MFC那一套机制,现在我们只需要在头文件和源文件加上2个宏,然后再编译的时候就将所有的产品类给串起来了,因为他们都是继承同一个基类,所以在使用的时候只需要知道基类的头文件和宏的定义就行了
这是我在main上写的使用代码
#include "stdafx.h"
#include "Common.h"
#include "BaseTest.h"
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
CBaseTest *pTest = NULL;
CRuntimeClass *pClass = NULL;
CRuntimeClass::pFirstClass;
for (pClass = CRuntimeClass::pFirstClass; pClass != NULL; pClass = pClass->m_pNextClass)
{
if (strcmp(pClass->m_lpszClassName, "CTestB") == 0)
{
pTest = (CBaseTest *)pClass->m_pfnCreateObject();
if (pTest != NULL)
{
pTest->FunOne();
}
}
}
return 0;
}
可以吧这段代码写入到工厂的创建方法上面,哪个字符串只是我模仿用户输入的字符串,工厂类只需要知道Common.h和BaseTest.h这2个头文件,其他不需要知道。增加了之类也不需要修改,现在我们看下子类需要加上上面东西才能实现这个
#pragma once
#include "BaseTest.h"
#include "Common.h"
class CTestA : public CBaseTest
{
DECLARE_DYNCREATE(CTestA)
public:
CTestA(void);
~CTestA(void);
public:
virtual void FunOne();
virtual void FunTwo();
virtual void FunThree();
};
#include "StdAfx.h"
#include "TestA.h"
#include <iostream>
using namespace std;
IMPLEMENT_DYNCREATE(CTestA);
CTestA::CTestA(void)
{
}
CTestA::~CTestA(void)
{
}
void CTestA::FunOne()
{
cout << "CTestA::FunOne" << endl;
}
void CTestA::FunTwo()
{
cout << "CTestA::FunTwo" << endl;
}
void CTestA::FunThree()
{
cout << "CTestA::FunThree" << endl;
}
在定义子类的时候,只需要添加2个宏就能实现这个动态创建的功能