2

我正在使用实体基础组件系统。

我有很多类型,stationary objects例如

  1. 墙 = 块
  2. 火炮塔=方块+射手
  3. 水炮台 = 方块 + 射手
  4. 地堡 = 方块 + 刷怪箱

这里是工厂stationary objects:-

class StationaryObject{
    enum typeOfObject_enum{WALL,FIRE_TURRET, ....};
    Entity* create(typeOfObject_enum theType){ //it is enum
        switch(theType){
            case WALL: ... create some mesh, some physic body  ....
            case FIRE_TURRET: .... create some mesh, some physic body+ unique logic 20 lines ....
            ....
        }
    }
}

它真的很好用。

问题:
现在我要创建 100 种类型Stationary objects,我应该将它存储在哪里?
将它们全部存储在课堂StationaryObject上会使课堂变得太大(?)。

请注意,每种类型的对象都有微小但独特的逻辑。

4

2 回答 2

4

您可以从每个对象工厂创建一个映射typeOfObject_enum,然后您可以根据需要在映射中注册工厂。

每个对象工厂都可能类似于std::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
}

现场演示。

或者,如果您愿意,可以使用抽象工厂类的实现:

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>();
    }
};

现场演示。

于 2016-09-01T08:51:43.923 回答
2

我没有使用过 C++,但听起来你可以混合 builder 和 factory 模式来获得你想要的,

class StationaryObject{
    Entity create(typeOfObject_enum theType){ //it is enum
        switch(theType){
            case WALL:
                return WallBuilder.Build();
            case FIRE_TURRET:
                return FireTurrentBuilder.Build();
            ....
        }
    }
}

您可以通过添加一个基类 BaseBuilder 来优化它,其中您对不同的实体有任何共同的逻辑

class BaseBuilder<T> {
   Mesh CreateMesh(){...}

   ....

   T Build();
}

class WallBuilder : BaseBuilder<Wall> {
   Wall Build(){
   }
}

使用这种方法,如果您愿意,可以使用枚举和构建器之间的映射,并摆脱 case 语句

于 2016-09-01T23:55:00.820 回答