搭建通用构造器

搭建通用构造器
1- 我们来确定我们的目标
    我们需要事先一个叫做xCreator的模板类,能够根据一个基类TBase实例化出一个构造器类,能够通过Support<TObject>()的形式来支持TBase的派生类TObject,并能够通过 Create<TObject>() 的形式来构造出这个TObject的对象。

2- 思考我们事先这个目标的理论基础
    我们需要为每个TObject,创建一个单独的内部构造器,在Support调用的时候,创建并存储这个内部构造器。当Create调用的时候,我们寻找这个内部构造器,并且通过这个构造器构造出TObject的对象。

3- 内部构造器
    在设计内部构造器的时候,因为需要一个通用的返回TBase的接口,所以,我们把这个接口做成一个虚接口。
class  xBaseCreator
{
public:
    virtual TBase 
* CreateObject() = 0;
}
;
    接下来,就是用模板来实现TObject的构造器了。
template  < class  TObject >
class  xObjectCreator :  public  xBaseCreator
{
public:
    TBase 
* CreateObject() return new TObject();}
}
;
    有了内部的构造器,我们构造出外部的框架xCreator
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;
    这里用的xVector是xlibplus的一部分,实际上它表现的跟STL的vector很相似,可以互换使用。
    下面就是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;
    }
;
    然后,修改xObjectCreator,提供一个静态变量,以及GetClassCode()的实现。
    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();
        
forint i = 0;i < m_vInnerCreators.size();i ++ )
            
if( m_vInnerCreators[i]->GetClassCode() == pClassCode )
                
return m_vInnerCreators[i]->CreateObject();
        
return NULL;
    }
    从代码中可以看出整个方法都集中在这个Create里面的内部构造器搜索上面。这种方法有点类似RTTI。


到现在为止,这个通用构造器就基本完成了。代码比较糙,只是用来说明这个方法。至于删除之类的代码,就比较简单了.

下面是完整的这个构造器的代码,以及测试代码。

#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();
        
forint 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;
}






你可能感兴趣的:(搭建通用构造器)