The ID based components require classes to create the actual instances. These are the Factory factories.
The library provides base classes for all required kinds of factories. The user often needs to specialise these base classes for its particular needs. Below a specialisation is presented for each factory class. Notice that the content for each class is similar:
- we have a constructor that requires a World instance; that is because the factory gets inserted in the world right from the constructor via addMyself() methods. The constructor also registers the ID that it uses (there may be multiple IDs, not just one as in these examples).
- a create() method also needs to be implemented. This is the principal method - the reason for the Factory class. The method recieves an ID as argument because each factory may be used to create any number of different objects that inherit the target type.
class FActor : public ActorFactory {
public:
FActor( World * w ) : ActorFactory( w ) {
w->insertId( IdKind, "kinds.test" );
addMyself( IdKind );
}
virtual Actor * create ( ID ) {
Actor * ret = new Actor( world() );
setDNA( ret );
return ret;
}
virtual void copyDefaultDNA ( DNA & destination ) {
destination = defaultDNA();
}
};
class FSensor : public SensorFactory {
public:
FSensor( World * w ): SensorFactory( w ) {
w->insertId( IdSensor, "sensors.test" );
addMyself( IdSensor );
}
virtual Sensor * create ( Actor * a, ID ) {
Sensor * ret = new Sensor( a );
return ret;
}
};
class FEvent : public EventFactory {
public:
FEvent( World * w ): EventFactory( w ) {
w->insertId( IdEvent, "events.test" );
addMyself( IdEvent );
}
virtual EventSource * create ( ID ) {
Ev * ret = new Ev( world() );
return ret;
}
};
class FActuator : public ActuatorFactory {
public:
FActuator( World * w ): ActuatorFactory( w ) {
w->insertId( IdActuator, "actuators.test" );
addMyself( IdActuator );
}
virtual Actuator * create ( Actor * a, ID ) {
Actuator * ret = new Actuator( a );
return ret;
}
};
class FBrain : public BrainFactory {
public:
FBrain( World * w ): BrainFactory( w ) {
w->insertId( IdBrain, "brains.test" );
addMyself( IdBrain );
}
virtual Brain * create ( Actor * a, ID ) {
Brain * ret = new Brain( a );
return ret;
}
};
class FReflex : public ReflexFactory {
public:
FReflex( World * w ): ReflexFactory( w ) {
w->insertId( IdReflex, "reflexes.test" );
addMyself( IdReflex );
}
virtual Reflex * create ( Actor * a, ID ) {
Reflex * ret = new Reflex( a );
return ret;
}
};
Not shown in previous example is that each factory has a averageDNA() method that the factory may use to initialise chunks of DNA for their respective types.
Once the world is created we create and insert an instance of each of these factories.
FActor * f_actor = new FActor( w );
DEC_REF(f_actor,f_actor);
FSensor * f_sensor = new FSensor( w );
DEC_REF(f_sensor,f_sensor);
FEvent * f_event = new FEvent( w );
DEC_REF(f_event,f_event);
FActuator * f_actuator = new FActuator( w );
DEC_REF(f_actuator,f_actuator);
FBrain * f_brain = new FBrain( w );
DEC_REF(f_brain,f_brain);
FReflex * f_reflex = new FReflex( w );
DEC_REF(f_reflex,f_reflex);
The world takes a reference for each factory so we can get rid of the constructor reference. When the world gets destructed these references are also released, causing the factories to be destroyed.