作者:饭中淹 来源:C++博客 酷勤网收集 2008-04-11
摘要
我们需要为每个TObject,创建一个单独的内部构造器,在Support调用的时候,创建并存储这个内部构造器。当Create调用的时候,我们寻找这个内部构造器,并且通过这个构造器构造出TObject的对象。 在设计内部构造器的时候,因为需要一个通用的返回TBase的接口
我们需要事先一个叫做xCreator的模板类,能够根据一个基类TBase实例化出一个构造器类,能够通过Support<TObject>()的形式来支持TBase的派生类TObject,并能够通过 Create<TObject>() 的形式来构造出这个TObject的对象。
2- 思考我们事先这个目标的理论基础
我们需要为每个TObject,创建一个单独的内部构造器,在Support调用的时候,创建并存储这个内部构造器。当Create调用的时候,我们寻找这个内部构造器,并且通过这个构造器构造出TObject的对象。
3- 内部构造器
在设计内部构造器的时候,因为需要一个通用的返回TBase的接口,所以,我们把这个接口做成一个虚接口。
class xBaseCreator

{
public:
virtual TBase * CreateObject() = 0;
};
template <class TObject>
class xObjectCreator : public xBaseCreator

{
public:
TBase * CreateObject()
{ return new TObject();}
};
template <class TBase>
class xCreator

{
class xBaseCreator
{
public:
virtual TBase * NewObject() = 0;
};
template <class TObject>
class xObjectCreator : public xBaseCreator
{
public:
TBase * CreateObject()
{ return new TObject();}
};
public:
template <class TObject>
void Support()
{
}
template <class TObject>
TBase * Create() 
{
}
};4- 实现Support
Support说白了,就是通过TObject来创建一个内部构造器,并保存在xCreator<TBase>里面。
那么我们需要在这个框架里加入一个容器来存储一系列的内部构造器。
xVector<xBaseCreator*> m_vInnerCreators;下面就是Support的实际代码,很简单的一句(没有做一些安全性和重复的检测)
template <class TObject>
void Support()
{
m_vInnerCreators.push_back( new xObjectCreator<TObject>() );
}5- 实现Create
Create是整个构造器的重头戏。我们需要找到一种方法,能够通过TObject来找到它所对应的内部构造器。
我们知道,同一个类中的静态成员的地址对于所有类成员来说,是一个相同的固定的地址。这样,这个地址,就可以标示一个特定的类。
然后,我们知道,模板参数相同的模板类实例类,是同一个类。
根据这两个,我们能够设计一种方法,通过静态成员的地址,来找到TObject对应的内部构造器的方法。下面就是这种方法的代码。
首先,修改xBaseCreator的接口,提供一个获取类的Code的接口,这个Code就是模板类中的一个静态变量的地址。
class xBaseCreator
{
public:
virtual TBase * CreateObject() = 0;
virtual void * GetClassCode() = 0;
};
template <class TObject>
class xObjectCreator : public xBaseCreator
{
public:
static void * GetCode()
{
static int nClassCode = 0;
return &nClassCode;
}
void * GetClassCode()
{ return GetCode();}
TBase * CreateObject()
{ return new TObject();}
};最后,我们把Create写好。
template <class TObject>
TBase * Create() 
{
void * pClassCode = xObjectCreator<TObject>::GetCode();
for( int i = 0;i < m_vInnerCreators.size();i ++ )
if( m_vInnerCreators[i]->GetClassCode() == pClassCode )
return m_vInnerCreators[i]->CreateObject();
return NULL;
}到现在为止,这个通用构造器就基本完成了。代码比较糙,只是用来说明这个方法。至于删除之类的代码,就比较简单了.
下面是完整的这个构造器的代码,以及测试代码。
#include "stdafx.h"
#include <conio.h>

template <class TBase>
class xCreator

{
class xBaseCreator
{
public:
virtual TBase * CreateObject() = 0;
virtual void * GetClassCode() = 0;
};
template <class TObject>
class xObjectCreator : public xBaseCreator
{
public:
static void * GetCode()
{
static int nClassCode = 0;
return &nClassCode;
}
void * GetClassCode()
{ return GetCode();}
TBase * CreateObject()
{ return new TObject();}
};
xVector<xBaseCreator*> m_vInnerCreators;
public:
template <class TObject>
void Support()
{
m_vInnerCreators.push_back( new xObjectCreator<TObject>() );
}
template <class TObject>
TBase * Create() 
{
void * pClassCode = xObjectCreator<TObject>::GetCode();
for( int i = 0;i < m_vInnerCreators.size();i ++ )
if( m_vInnerCreators[i]->GetClassCode() == pClassCode )
return m_vInnerCreators[i]->CreateObject();
return NULL;
}
};
class CBase

{
public:
virtual int GetCode() const
{ return 0;}
};
class CTest1 : public CBase

{
public:
virtual int GetCode() const
{ return 1;}
};
class CTest2 : public CBase

{
public:
virtual int GetCode() const
{ return 2;}
};
xCreator<CBase> testcreator;
int _tmain(int argc, _TCHAR* argv[])

{
testcreator.Support<CTest1>();
testcreator.Support<CTest2>();
CBase * p1 = testcreator.Create<CTest1>();
CBase * p2 = testcreator.Create<CTest2>();
printf( "code = %u / %u\n", p1->GetCode(), p2->GetCode() );
getch();
return 0;
}
来自:http://www.cppblog.com/johndragon/archive/2008/04/01/45862.html

