You could create a map from typeOfObject_enum
to each object factory and then you can register factories in the map as you wish.
Each object factory could be something like astd::function<std::unique_ptr<Entity>()>
:
enum class StationaryObjectType{WALL, FIRE_TURRET, WATER_TURRET};
const size_t STATIONARY_OBJECT_TYPE_COUNT = 3;
using EntityFactory = std::function<std::unique_ptr<Entity>()>;
class StationaryObjectFactory {
std::array<EntityFactory, STATIONARY_OBJECT_TYPE_COUNT> factory_map;
public:
void registerFactory(StationaryObjectType type, EntityFactory factory){
factory_map[static_cast<size_t>(type)] = std::move(factory);
}
std::unique_ptr<Entity> create(StationaryObjectType type){
auto factory = factory_map[static_cast<size_t>(type)];
if (!factory)
return nullptr;
return factory();
}
};
int main() {
StationaryObjectFactory factory;
// Register lambdas as the factory objects
factory.registerFactory(StationaryObjectType::WALL, []{
return std::make_unique<Wall>();
});
factory.registerFactory(StationaryObjectType::FIRE_TURRET, []{
return std::make_unique<FireTurret>();
});
auto wall = factory.create(StationaryObjectType::WALL);
auto fire_turret = factory.create(StationaryObjectType::FIRE_TURRET);
auto water_turret = factory.create(StationaryObjectType::WATER_TURRET);
assert(wall != nullptr);
assert(fire_turret != nullptr);
assert(water_turret == nullptr); // No WATER_TURRET factory registered
}
Live demo.
Or if you prefer, you could use implementations of an abstract factory class:
class EntityFactory {
public:
virtual ~EntityFactory(){}
virtual std::unique_ptr<Entity> operator()() = 0;
};
class WallFactory : public EntityFactory {
public:
std::unique_ptr<Entity> operator()() override {
return std::make_unique<Wall>();
}
};
class FireTurretFactory : public EntityFactory {
public:
std::unique_ptr<Entity> operator()() override {
return std::make_unique<FireTurret>();
}
};
Live demo.