00001 /* -*- mode: c++ -*- */ 00002 00014 #ifndef _Factory_H_ 00015 #define _Factory_H_ 00016 00017 #include "FactoryException.h" 00018 00019 #ifdef _MSC_VER 00020 #include "msdevstudio/MSconfig.h" 00021 #endif 00022 00023 #include <map> 00024 #include <vector> 00025 00041 template < class Type > class Factory 00042 { 00043 private: 00044 00046 Factory ( const Factory< Type > & ); 00047 00048 protected: 00049 00051 std::map < std::string, Type * > m_types; 00052 00056 std::vector< std::string > m_names; 00057 00060 Factory ( ); 00061 00064 virtual ~Factory(); 00065 00066 public: 00067 00069 void add ( Type * ); 00070 00074 bool exists ( const std::string & name ) const; 00075 00079 Type * prototype ( const std::string & name ) const; 00080 00085 Type * create ( const std::string & name ); 00086 00088 const std::vector< std::string > & names (); 00089 00090 }; 00091 00092 template < class Type > 00093 Factory < Type >::Factory ( ) 00094 { 00095 } 00096 00097 template< class Type > 00098 Factory<Type>::~Factory () 00099 { 00100 typename std::map < std::string, Type * > ::iterator first 00101 = m_types.begin(); 00102 for ( ; first != m_types.end(); ++first ) { 00103 delete first->second; 00104 } 00105 00106 m_types.clear (); 00107 } 00108 00109 template< class Type > 00110 void Factory<Type>::add ( Type * obj ) 00111 { 00112 const std::string & name = obj->name (); 00113 m_types[name] = obj; 00114 } 00115 00116 template < class Type > 00117 bool Factory < Type>:: 00118 exists ( const std::string & name ) const 00119 { 00120 // Don't use map::operator[]() to find the name, as it will create 00121 // one if it doesn't exist. 00122 typename std::map< std::string, Type * >::const_iterator it 00123 = m_types.find ( name ); 00124 00125 return it != m_types.end (); 00126 } 00127 00128 00129 template< class Type > 00130 Type * Factory<Type>::prototype ( const std::string & name ) const 00131 { 00132 // Don't use map::operator[]() to find the name, as it will create 00133 // one if it doesn't exist. 00134 typename std::map< std::string, Type * >::const_iterator it 00135 = m_types.find ( name ); 00136 if ( it == m_types.end () ) throw FactoryException ( name ); 00137 00138 return it->second; 00139 } 00140 00141 template< class Type > 00142 Type * Factory<Type>::create ( const std::string & name ) 00143 { 00144 Type * obj = prototype ( name ); 00145 if ( obj == 0 ) { 00146 return 0; 00147 } 00148 00149 return obj->clone (); 00150 } 00151 00152 template< class Type > 00153 const std::vector< std::string > & Factory<Type>::names () 00154 { 00155 m_names.clear (); 00156 typename std::map <std::string, Type *>::const_iterator it 00157 = m_types.begin (); 00158 for ( ; it != m_types.end (); ++it ) { 00159 m_names.push_back ( it->first ); 00160 } 00161 return m_names; 00162 } 00163 00164 #endif // _Factory_H_