Как ссылаться на поля перечисления внутри Builder другого класса? - PullRequest
0 голосов
/ 11 января 2019

Я использую шаблон Builder для создания объектов Item в своей игре, и я хочу иметь возможность использовать префиксы элементов и суффиксы для генерации случайных элементов, как в Item.builder().random().build(). Префикс и Суффикс - это перечисления с разорванными полями. Все они имеют поля name, но некоторые имеют, например, поля damage и luck. Как мне получить доступ к полям перечислений из компоновщика?

У меня есть открытые методы в каждом перечислении, которые возвращают случайный префикс и суффикс, метод randomize моего Item Builder вызывает их и сохраняет аффиксы локально. Но я не могу понять их переменные-члены с помощью отражения. prefix.getClass().getDeclaredField("name").toString возвращает java.lang.String roan.ItemPrefix$2.name вместо его фактического имени. К тому же мне это кажется вздорным.

Enum:

enum Prefix {
    ARROGANT {
        String name = "Arrogant ";
        int damage = 20;
        int luck = 2;
    },
    BLOODY {
        String name = "Bloody ";
        int damage = 30;
    },
    CURIOUS {
        String name = "Curious ";
        int luck = 4;
    },

    private static final int size = Prefix.values().length;

    public static Prefix randomPrefix() {
        return Prefix.values()[Dice.roll(Prefix.size)];
    }
}

Builder:

public static abstract class Builder<T extends Builder<T>> {
    // Default values
    private String name = "itemName"; 
    private int damage = 5;
    private int luck = 0;  

    protected abstract T self();

    public T name(String name) {
        this.name = name;
        return self();
    }

    // More builder methods
    ...

    // PROBLEMATIC CODE
    public T random() {
        Prefix prefix = Prefix.randomPrefix();
        this.name = prefix.getClass().getDeclaredField("name").toString();
        return self();
        }

        public Item build() {
            return new Item(this);
        }
    }
}

// Builder helper classes
...

В идеале он собирал бы полностью сформированные элементы, используя поля-члены перечисленных ему перечислений. Я использую enum Prefix, а не массив объектов Prefix, потому что я хочу использовать некоторые EnumSets в другом месте для подклассов Item, таких как Armor, которые могут использовать только определенные префиксы.

1 Ответ

0 голосов
/ 11 января 2019

Ваш текущий дизайн зависит от 3 анонимных подклассов префикса enum. Это не обязательно. Скорее попробуйте это:

enum Prefix {
  ARROGANT ("Arrogant ",20,2), BLOODY("Bloody ",30,0), CURIOUS("Curious ",5, 4);

  public String name = "itemName"; 
  public int damage = 5;
  public int luck = 0;  

  Prefix(String name, int damage, int luck) {
    this.name = name;
    this.damage = damage;
    this.luck = luck;
  }

  ...
}

Следовательно, вам не понадобится рефлексия для доступа к вашим полям.

Если вы действительно хотите, чтобы альтернативы arrogant, bloody, curious имели разные схемы, решение для перечисления неверно. Скорее выберите случайный список в списке фабрик, каждый из которых возвращает полностью правильный сконфигурированный элемент для этого случайного выбора.

...