#ifndef _utl_ObjectFactory_h_ #define _utl_ObjectFactory_h_ /** \file Object Factory template. \author Lukas Nellen \version $Id$ \date 10 Mar 2004 */ static const char CVSId_utl_ObjectFactory[] = "$Id$"; #include namespace utl { /** \class FactoryErrorIgnore ObjectFactory.h "utl/ObjectFactory.h" \brief Default error policy for ObjectFactory: return 0 The policy is defined by the implementation of the static function \c Unregistered. In alternative inmplementations, this functions could throw an exception or try to load a library dynamically. \author Lukas Nellen \date 10 Mar 2004 \ingroup stl */ template class FactoryErrorIgnore { public: static ObjectPtrType Unregistered(const IdentifierType&) { return 0; } template static ObjectPtrType Unregistered(const IdentifierType& /*theId*/, const ArgumentType& /*theArg*/) { return 0; } template static ObjectPtrType Unregistered(const IdentifierType& /*theId*/, const Argument1Type& /*theArg1*/, const Argument2Type& /*theArg2*/) { return 0; } }; /** \class ObjectFactory ObjectFactory.h "utl/ObjectFactory.h" \brief Template for object factory The implementation relies on static objects to implement a mono-state like structure without having to instantiate the factory. The template allows for factory functions or functors with 0, 1, and 2 arguments. It is trivial to add more creation functions to allow for more arguments. It is checked at compile time that the CreatorType and the form of the Create call match. The design is inspired by the object factory in the book Modern C++ Design by Andrei Alexandrescu. \author Lukas Nellen \date 10 Mar 2004 \ingroup stl */ template > class ObjectFactory : public FactoryErrorPolicy { private: typedef std::map RegistryType; public: typedef ObjPtrType ObjectPtrType; typedef IdentType IdentifierType; typedef CreatType CreatorType; typedef typename RegistryType::const_iterator Iterator; public: ObjectFactory(); ~ObjectFactory(); /// Register a factory function with an ID static bool Register(const IdentifierType& theId, const CreatorType& theCreator) { if (!fgRegistry) fgRegistry = new RegistryType; return fgRegistry->insert(std::make_pair(theId, theCreator)).second; } /// Get number of object types know to this factory static unsigned int GetNumberOfCreators() { return fgRegistry ? fgRegistry->size() : 0; } /// Create an object (0-argument constructor) static ObjectPtrType Create(const IdentifierType& theId) { if (!fgRegistry) return ObjectFactory::Unregistered(theId); const Iterator it = fgRegistry->find(theId); if (it != fgRegistry->end()) return (it->second)(); else return ObjectFactory::Unregistered(theId); } /// Create an object (1-argument constructor) template static ObjectPtrType Create(const IdentifierType& theId, const ArgumentType& theArg) { if (!fgRegistry) return ObjectFactory::Unregistered(theId, theArg); const Iterator it = fgRegistry->find(theId); if (it != fgRegistry->end()) return (it->second)(theArg); else return ObjectFactory::Unregistered(theId, theArg); } /// Create an object (2-argument constructor) template static ObjectPtrType Create(const IdentifierType& theId, const Argument1Type& theArg1, const Argument2Type& theArg2) { if (!fgRegistry) return ObjectFactory::Unregistered(theId, theArg1, theArg2); const Iterator it = fgRegistry->find(theId); if (it != fgRegistry->end()) return (it->second)(theArg1, theArg2); else return ObjectFactory::Unregistered(theId, theArg1, theArg2); } /// Begin iterator over the internal map (read only) static Iterator Begin() { if (!fgRegistry) fgRegistry = new RegistryType; return fgRegistry->begin(); } /// End iterator over the internal map (read only) static Iterator End() { if (!fgRegistry) fgRegistry = new RegistryType; return fgRegistry->end(); } private: ObjectFactory(const ObjectFactory& theObjectFactory); ObjectFactory& operator=(const ObjectFactory& theObjectFactory); static RegistryType* fgRegistry; }; // ObjectFactory // the definition of the registry, which cannot be done in the class defn. template typename ObjectFactory::RegistryType* ObjectFactory::fgRegistry = 0; } // utl #endif // _utl_ObjectFactory_h_ // Configure (x)emacs for this file ... // Local Variables: // mode: c++ // compile-command: "make -C .. -k" // End: