In C++, you would typically use the Abstract Factory design pattern.
The point is: "the decision about the type of actor to create should not be the responsibility of ActorFactory::create()." In your case, this method should not decide which class to instantiate based on a string but would rather rely on a type; this type is the actual factory class.
Each actor class has its own factory class: TrollFactory, DragonFactory, etc. deriving from a base class ActorFactory2 (trailing 2 because ActoryFactory is already taken);
Each specialized factory class implements a virtual create() method without parameter returning a pointer to a newly created actor class;
If you need parameters to construct an actor, pass them to the factory object before creating the actor: pass them in the ctor and store them as member variables; create() will retrieve them later upon creation of the actor;
This way, you can easily pass different arguments for different actors and your factory mechanism will be scalable (a step toward the Open/Closed principle);
Now, ActorFactory::create() accepts a pointer to an object deriving from ActorFactory2 and calls the ActorFactory2::create() method: it will create the requested actor with appropriate arguments without switch statement.
class ActorFactory2
{
string m_name; // Each IA actor has a name
int m_hp; // and some HP
public:
ActorFactory2( const string &p_name, int p_hp )
: m_name( p_name ), m_hp( p_hp ) {}
virtual IActor * create() const = 0;
};
class TrollFactory : public ActorFactory2
{
// No special argument needed for Troll
public:
TrollFactory( const string &p_name, int p_hp )
: ActorFactory2( p_name, p_hp ) {}
virtual IActor * create() const { return new Troll( m_name, m_hp ); }
};
class DragonFactory : public ActorFactory2
{
FlameType m_flame; // Need to indicate type of flame a dragon spits
public:
DragonFactory( const string &p_name, int p_hp, const FlameType &p_flame )
: ActorFactory2( p_name, p_hp )
, m_flame( p_flame ) {}
virtual IActor * create() const { return new Dragon( m_name, m_hp, m_flame ); }
};
IActor * ActorFactory::create( const ActorFactory2 *factory )
{
return factory->create();
}
int main( int, char ** )
{
ActorFactory af;
...
// Create a dragon with a factory class instead of a string
ActorFactory2 *dragonFactory = new DragonFactory( "Fred", 100, RedFlames );
IActor *actor = af.create( dragonFactory ); // Instead of af.create( "dragon", ... )
delete dragonFactory;
}