You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Artemis-odb框架:规避庞大EntityManager子类的Entity实例化方案问询

拆分Artemis-odb实体创建逻辑的实用方案

嘿,我太懂你这种烦恼了——把所有实体创建逻辑塞进一个EntityManager子类里,到后期代码臃肿得像个大球,找个方法都要翻半天!针对Artemis-odb里的实体实例化拆分,我有几个实战中常用的方案,你可以按需选择:

1. 按实体类型拆分独立工厂类

这是最直观的拆分方式:给每种实体(比如工人、建筑)单独写一个工厂类,专门负责该类型实体的所有创建逻辑,依赖EntityManager完成实际的实体创建和组件添加。

举个工人实体工厂的例子:

public class WorkerFactory {
    private final EntityManager entityManager;

    // 通过构造注入EntityManager,避免硬依赖
    public WorkerFactory(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public Entity createMinerWorker(int x, int y) {
        Entity worker = entityManager.createEntity();
        worker.edit()
            .add(new PositionComponent(x, y))
            .add(new WorkerComponent(WorkerType.MINER))
            .add(new HealthComponent(100))
            .add(new AnimationComponent("miner_sprite"));
        return worker;
    }

    public Entity createFarmerWorker(int x, int y) {
        Entity worker = entityManager.createEntity();
        worker.edit()
            .add(new PositionComponent(x, y))
            .add(new WorkerComponent(WorkerType.FARMER))
            .add(new HealthComponent(120))
            .add(new AnimationComponent("farmer_sprite"));
        return worker;
    }
}

建筑工厂的逻辑类似:

public class BuildingFactory {
    private final EntityManager entityManager;

    public BuildingFactory(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public Entity createIronMine(int x, int y) {
        Entity mine = entityManager.createEntity();
        mine.edit()
            .add(new PositionComponent(x, y))
            .add(new BuildingComponent(BuildingType.IRON_MINE))
            .add(new ProductionComponent(ResourceType.IRON, 5))
            .add(new HealthComponent(500));
        return mine;
    }
}

使用时只需要在游戏初始化时实例化这些工厂,传入EntityManager即可:

EntityManager em = new EntityManager();
WorkerFactory workerFactory = new WorkerFactory(em);
BuildingFactory buildingFactory = new BuildingFactory(em);

// 创建矿工
Entity miner = workerFactory.createMinerWorker(10, 20);
// 创建铁矿
Entity ironMine = buildingFactory.createIronMine(30, 40);

这种方式的核心优势是职责单一,每个工厂只聚焦一类实体,代码可读性和维护性拉满——新增实体类型只需要加新的工厂类,完全不会污染原有代码。

2. 实体原型+复制模式

如果你的同类型实体有大量重复的基础配置(比如所有矿工的初始血量、精灵都一致),可以先创建一个“原型实体”,然后通过复制原型来快速生成新实体。Artemis-odb原生支持实体复制,结合工厂管理原型会更高效:

public class EntityPrototypeFactory {
    private final EntityManager entityManager;
    private final Map<String, Entity> prototypes = new HashMap<>();

    public EntityPrototypeFactory(EntityManager entityManager) {
        this.entityManager = entityManager;
        initPrototypes();
    }

    private void initPrototypes() {
        // 创建矿工原型
        Entity minerPrototype = entityManager.createEntity();
        minerPrototype.edit()
            .add(new WorkerComponent(WorkerType.MINER))
            .add(new HealthComponent(100))
            .add(new AnimationComponent("miner_sprite"));
        prototypes.put("miner", minerPrototype);

        // 创建农民原型
        Entity farmerPrototype = entityManager.createEntity();
        farmerPrototype.edit()
            .add(new WorkerComponent(WorkerType.FARMER))
            .add(new HealthComponent(120))
            .add(new AnimationComponent("farmer_sprite"));
        prototypes.put("farmer", farmerPrototype);
    }

    public Entity createFromPrototype(String prototypeId, int x, int y) {
        Entity prototype = prototypes.get(prototypeId);
        if (prototype == null) {
            throw new IllegalArgumentException("Unknown prototype: " + prototypeId);
        }
        // 复制原型实体
        Entity newEntity = entityManager.copy(prototype);
        // 覆盖位置组件(每个实体位置不同)
        newEntity.edit().add(new PositionComponent(x, y));
        return newEntity;
    }
}

使用示例:

EntityPrototypeFactory prototypeFactory = new EntityPrototypeFactory(em);
Entity miner = prototypeFactory.createFromPrototype("miner", 10, 20);

这种方式能极大减少重复代码,修改原型就能批量更新同类型实体的基础属性,非常适合批量生成的实体。

3. 构建器模式(灵活配置场景)

如果实体的组件配置需要灵活定制(比如偶尔要创建血量更高的特殊工人),构建器模式会是绝佳选择——它允许你链式调用配置实体的各个属性,代码可读性拉满:

public class WorkerBuilder {
    private final EntityManager entityManager;
    private int x = 0;
    private int y = 0;
    private WorkerType type = WorkerType.MINER;
    private int health = 100;
    private String sprite = "default_worker";

    public WorkerBuilder(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public WorkerBuilder position(int x, int y) {
        this.x = x;
        this.y = y;
        return this;
    }

    public WorkerBuilder type(WorkerType type) {
        this.type = type;
        // 根据类型自动设置默认属性
        if (type == WorkerType.FARMER) {
            this.health = 120;
            this.sprite = "farmer_sprite";
        } else if (type == WorkerType.MINER) {
            this.health = 100;
            this.sprite = "miner_sprite";
        }
        return this;
    }

    public WorkerBuilder health(int health) {
        this.health = health;
        return this;
    }

    public WorkerBuilder sprite(String sprite) {
        this.sprite = sprite;
        return this;
    }

    public Entity build() {
        Entity worker = entityManager.createEntity();
        worker.edit()
            .add(new PositionComponent(x, y))
            .add(new WorkerComponent(type))
            .add(new HealthComponent(health))
            .add(new AnimationComponent(sprite));
        return worker;
    }
}

使用时可以灵活定制:

WorkerBuilder builder = new WorkerBuilder(em);
Entity superMiner = builder.position(10,20)
                           .type(WorkerType.MINER)
                           .health(150) // 自定义血量
                           .sprite("super_miner_sprite")
                           .build();

这种方式完美解决了构造函数参数过多的问题,同时保留了配置的灵活性,适合需要个性化定制的实体场景。


内容的提问来源于stack exchange,提问作者Kerial

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:52:58