Просто нереально простая и в тоже время для меня весьма приятная фабрика. Сие чудо было сотворенно под влиянием Александреску и ревью 3D движков. Приятного аппетита)
#ifndef __CMN_OBJ_FACTORY_H__
#define __CMN_OBJ_FACTORY_H__
#include "cmnNonCopyable.h"
#include < map >
#include < string >
#include < memory >
#include < assert.h >
namespace utils
{
namespace factory
{
template < typename TIdentifierType, class TObjectType >
struct default_err_policy
{
TObjectType* OnUnknownType( TIdentifierType )
{
assert( false );
return NULL;
}
};
template
<
typename TObjectType,
typename TIdentifierType = std::string,
typename TCreatorCallback = TObjectType * ( * ) ( ),
typename TCopyablePolicy = noncopyable,
template < typename, class > class error_policy = factory::default_err_policy
>
class object_factory
: public error_policy < TIdentifierType, TObjectType >
, TCopyablePolicy
{
class Constructor
{
Constructor();
public:
explicit Constructor( TCreatorCallback func ) : func_( func )
{ }
template < typename TType >
explicit Constructor( TType* dumb ) : func_( NULL ), type_creator_( new TypeCreator < TType > )
{ }
TObjectType* operator( )( )
{
return ( func_ ? func_( ) : ( type_creator_ ? type_creator_->Create() : NULL ) );
}
private:
struct TypeCreatorBase
{
virtual TObjectType* Create() = 0;
};
template < typename TType >
struct TypeCreator
: public TypeCreatorBase
, TCopyablePolicy
{
virtual TObjectType* Create()
{
return new TType();
}
};
private:
TCreatorCallback func_;
std::tr1::shared_ptr < TypeCreatorBase > type_creator_;
};
typedef std::map < TIdentifierType, Constructor > fmap;
fmap factory_;
public:
template < typename TType >
bool Register( const TIdentifierType& id )
{
return factory_.insert( fmap::value_type( id, Constructor( ( TType* ) NULL ) ) ).second != 0;
}
template < TCreatorCallback func >
bool Register( const TIdentifierType& id )
{
return factory_.insert( fmap::value_type( id, Constructor( func ) ) ).second != 0;
}
bool Unregister( const TIdentifierType& id )
{
return factory_.erase( id ) != 0;
}
TObjectType* CreateObject( const TIdentifierType& id )
{
typename fmap::iterator iter = factory_.find( id );
if ( iter != factory_.end() )
{
return ( iter->second )( );
}
return OnUnknownType( id );
}
};
} // factory
} // utils
#endif
Тест сего творения:
#include < iostream >
#include "cmnObjFactory.h"
using namespace std;
using namespace utils::factory;
//---------------------------------
struct IBase { virtual void Test() = 0; };
struct Test1 : IBase {
Test1() { cout << "Create 1" << endl; }
virtual void Test() { } };
struct Test2 : IBase {
Test2(int i) { cout << "Create 2" << endl; }
virtual void Test() { } };
IBase* Create() { return new Test2(2); }
//---------------------------------
object_factory < IBase > g_factory;
int _tmain(int argc, _TCHAR* argv[])
{
g_factory.Register < Test1 > ("test1");
g_factory.Register < Create > ("test2");
IBase* pObj1 = g_factory.CreateObject("test1");
IBase* pObj2 = g_factory.CreateObject("test2");
return 0;
}
No comments:
Post a Comment