enum singleton, ссылка на интерфейс, экземпляр на имя строки

Спасибо за просмотр моего вопроса, на который я не смог найти ответ в моих поисках / книгах. Я изучаю Java, написав roguelike, но я думаю, что этот вопрос больше связан с Java, чем с игрой. Не стесняйтесь обучать меня, если я ошибаюсь.

У меня есть похожие классы, которые я хочу, чтобы у каждого были определенные способности. Способности - это enum singletons с набором стандартных имен методов, которым я бы передавал Actor - я хотел избежать реализации методов из интерфейса в каждом классе Actor, и мне просто очень понравилось предполагаемое использование этого подхода по мере продвижения вперед. Я родом из shell / perl и не могу сказать, не думаю ли я о ООП, или у меня что-то полезное, и у меня еще нет навыков, чтобы справиться с этим.

addAbility (String) в StdActor - то, где это наконец сломалось в этом эксперименте.

Вопрос в том, делаю ли я здесь что-то неправильно? Если нет, как я могу это реализовать?

интерфейс для манипулирования способностями:

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 и в других местах. это, вероятно, должно быть взорвано с орбиты.

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. Я попробовал то, что вы предложили, и он, кажется, делает то, что я надеялся. Похоже, я был только в сорняках и должен был быть отозван.

1 ответ

Решение

Новый класс:

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

StdActor:

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

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

подкласс:

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
Другие вопросы по тегам