// 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;
}
   |