// Copyright (c) 2000 Stuart McConnell
//
// stuart_mcconnell@mail.com
//
#if defined ( WIN32 )
#pragma warning ( disable : 4786 )
#endif
#include <iostream>
#include <string>
#include <map>
using namespace std;
// template based factory
template <typename T>
class factory
{
public:
typedef typename T base_type;
class creator_base
{
public:
base_type* operator()() { return create(); }
virtual base_type* create() const = 0;
};
template <typename D>
class creator : public creator_base
{
public:
typedef typename D derived_type;
virtual base_type* create() const { return new derived_type(); }
};
typedef std::map<std::string, creator_base*> string_creator_map;
void register_object( const std::string& classname, creator_base* creator )
{
string_creator_map::iterator iter = _classes.find( classname );
if ( iter == _classes.end() )
{
_classes[classname] = creator;
}
}
base_type* create_object( const std::string& classname )
{
base_type* obj = 0;
string_creator_map::iterator iter = _classes.find( classname );
if ( iter != _classes.end() )
{
obj = (*(*iter).second)();
}
return obj;
}
protected:
string_creator_map _classes;
};
// sample test program with an example object hierarchy
class object
{};
class game_object : public object
{};
class light_object : public object
{};
// create an instance of a factory for 'object' derived classes
static factory<object> f;
// simple wrapper for creating an object
object* create( const std::string& classname )
{
object* obj = f.create_object( classname );
cout << "create_object(" << classname << ")\t:\t" << ( (obj) ? "successful" : "failed") << endl << endl;
return obj;
}
int main( int argc, char* argv[] )
{
// register the sample derived objects
f.register_object( "game_object", new factory<object>::creator<game_object>() );
f.register_object( "light_object", new factory<object>::creator<light_object>() );
// try to create instances of the objects
object* game = create( "game_object" );
object* light = create( "light_object" );
object* other = create( "other_object" );
// cleanup
delete game;
delete light;
delete other;
return 0;
}
|