枚举单例,通过接口引用,通过字符串名称实例

enum singleton, referenced by interface, instance by string name

感谢您查看我的问题,我尚未在 searches/books 中成功找到答案。我正在通过编写 roguelike 来学习 java,但我认为这个问题与 java 相关而不是与游戏相关。如果我错了,请随时教育我。

我有类似的 class 我希望每个人都有特定的能力。这些能力是带有一组标准方法名称的枚举单例,我会将 Actor 传递给它们 - 我想避免从每个 Actor class 中的接口实现方法,并且真的很喜欢这种方法的设想使用,因为我前进。我来自 shell/perl 背景,不知道我是否只是没有考虑 OOP,或者我是否正在做一些有用的事情但还没有实现它的技能。

StdActor 中的 addAbility(String) 是它在本实验中最终崩溃的地方。

问题是 - 我在这里做错了什么吗?如果没有,我该如何实现?

技能操作界面:

public interface ActorAbility {

    // doesn't work, but need something to enable
    // instance retrieval for addAbility...
    public ActorAbility getInstance();

    public void act(Actor actor);

    public boolean isTickable();

}

接口的净化实现:

public enum ActorMove implements ActorAbility {
    INSTANCE;

    private ActorMove() {
    }

    public ActorAbility getInstance() {
        return INSTANCE;
    }

    public void act(Actor actor) {
        log.debug("Move");
    }

    public boolean isTickable() {
        return true;
    }

}

净化该能力的使用。反复试验 运行 疯狂。 addAbility(String) 损坏,来自 SO 和其他地方的 copy/paste。它可能需要从轨道上被摧毁。

public class StdActor implements Actor {
    private HashSet<ActorAbility> abilities = new HashSet<>();

    // this whole method is wrecked
    public void addAbility(String ability) {
        // Class<? extends ActorAbility> action;  // in a maze of twisty passages...
        ActorAbility actionInstance = null;
        try {
            // action = Class.forName("game3.Actors.Abilities." + ability);
            actionInstance = ActorAbility.valueOf("game3.Actors.Abilities."
                + ability);
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.abilities.add(actionInstance);
    }
}

用例:

public class StdCharClass extends StdActor {

    public StdCharClass() {
        // I like this because it's clean and easily
        // changeable
        addAbility("ActorMove");
    }
}

未来计划使用:

HashSet<ActorAbility> abilities = actor.getAbilities();
for (ActorAbility ability : abilities) {
    if (ability.isTickable()) {
        ability.act(actor);
    }
}

谢谢!

编辑: 感谢您的快速评论,JB。我尝试了你的建议,它似乎做了我希望的事情。看来我只是在杂草丛生,需要被拉回来。

新 class:

public enum Ability {
    MOVE(ActorMove.INSTANCE), FIGHT(ActorFight.INSTANCE);

    private ActorAbility ability;

    private Ability(ActorAbility abilityClass) {
        this.ability = abilityClass;
    }

    public ActorAbility getAbility() {
        return this.ability;
    }
}  

标准演员:

public class StdActor implements Actor {
private HashSet<Ability> abilities = new HashSet<>();

public void addAbility(Ability ability) {
    this.abilities.add(ability);
}

subclass:

public class StdCharClass extends StdActor {

    public StdCharClass() {
        addAbility(Ability.MOVE);
    }

}

最后,用法:

HashSet<Ability> abilities = bob.getAbilities();
for (Ability ability : abilities) {
    ActorAbility abilityClass = ability.getAbility();
    if (abilityClass.isTickable()) {
        abilityClass.act(bob);
    }
}

输出!

12:44:15.835 [main] DEBUG ActorMove - Move