This is very fascinating. I've spent some time on factory
pattern, but I don't like to write so many switch-case in my
system. One further question is that if it truly fit my
future requirement since the classes may get enriched someday.
The usual solution is to use some sort of dynamic registration
with a map. And you don't need to use dynamic linking for it to
work. Basically, for each type, you define a static factory
object for that specific type, whose constructor registers it
with the factory map. Roughly speaking:
class AbstractFactory
{
public:
virtual ~AbstractFactory() {}
Base* create() const = 0 ;
protected:
AbstractFactory( std::string const&
typename ) ;
} ;
class FactoryMap
{
typedef std::map< std::string, AbstractFactory const* >
Map ;
public:
static FactoryMap&
instance() ;
void enrol( std::string const& typename,
AbstractFactory const* factory ) ;
Base* create( std::string const& typename ) const ;
private:
Map myMap ;
// plus the usual singleton stuff...
} ;
AbstractFactory::AbstractFactory(
std::string const& typename )
{
FactoryMap::instance().enrol( typename, this ) ;
}
void
FactoryMap::enrol(
std::string const& typename,
AbstractFactory const*
factory )
{
assert( myMap.find( typename ) == myMap.end() ) ;
myMap.insert( Map::value_type( typename, factory ) ) ;
}
Base*
FactoryMap::create(
std::string const& typename ) const
{
Map::const_iterator entry
= myMap.find( typename ) ;
return entry == myMap.end()
? NULL
: entry->second->create() ;
}