Как создать неизменный построитель неизменного класса, который содержит множество? - PullRequest
1 голос
/ 22 марта 2011

Я пытаюсь создать неизменный строитель неизменного класса, который содержит набор. Это должен быть неизменный набор, но сейчас я должен использовать обычные классы JCF. Используя стандартный пример пиццы, у меня есть база пиццы в качестве обязательного параметра и начинки в качестве необязательного, 0 или больше разрешено. Я предполагаю, что каждый вызов addToppings() создаст нового неизменного компоновщика с набором начинок, а затем, наконец, при вызове build будет доставлен объект Pizza. Я просто не знаю, как создать неизменный набор toppings. Вот мой код:

public class Pizza {

private Pizza(Base base, Set<Topping> toppings) {
    this.base = base;
    this.toppings = toppings;
}

public static PizzaBuilder createBuilder(Base pizzaBase) {
    return new PizzaBuilder(new Pizza(pizzaBase, null));
}

public static class PizzaBuilder {
    private PizzaBuilder(Pizza pizza) {
        this.pizza = pizza;
    }

    public PizzaBuilder addTopping(Topping topping) {
        return new PizzaBuilder(new Pizza(pizza.base, ???));
    }

    public Pizza build() {
        return pizza;
    }

    final private Pizza pizza;
}

public Collection<Topping> getToppings() {
    return Collections.unmodifiableSet(toppings);
}

enum Base {DEEP_PAN, THIN}
enum Topping {MOZZARELLA, TOMATO, ANCHOVIES, PEPPERONI}

final private Base base;
final private Set<Topping> toppings;

}

Я знаю, что это отклонение от «стандартного» нового шаблона компоновщика, но я считаю, что хранение и копирование значений там не элегантно, поскольку целевой класс уже определяет, какие поля необходимы.

Ответы [ 2 ]

3 голосов
/ 22 марта 2011
public PizzaBuilder addTopping(Topping topping) {
    Set<Topping> toppings = null;
    if (pizza.toppings == null)
        toppings = new LinkedHashSet<Topping>();
    else
        toppings = new LinkedHashSet<Topping>(pizza.toppings);
    toppings.add(topping);
    return new PizzaBuilder(new Pizza(pizza.base, toppings));
}

Это то, что вас интересует? Я выбрал LinkedHashSet для поддержания порядка начинки.

1 голос
/ 22 марта 2011

Вы можете клонировать старый набор, добавить новую запись и затем использовать ее. EnumSet более эффективно, чем Set, кстати:

final private EnumSet<Topping> toppings;

public PizzaBuilder addTopping(Topping topping) {
    EnumSet<Topping> newToppings = EnumSet.of(topping);
    if (toppings != null) {
        newToppings.addAll(toppings);
    }
    return new PizzaBuilder(new Pizza(pizza.base, newToppings));
}

Обратите внимание, что это не сохранение потока.

Java не имеет «настоящих» неизменяемых наборов (где добавление или удаление элементов возвращает новый набор, аналогично методам String в Java), но Scala имеет .

...