уроки Шаблон Builder в эффективной Java




паттерны проектирования уроки (7)

Я лично предпочитаю использовать другой подход, когда у вас есть 2 разных класса. Поэтому вам не нужен статический класс. Это в основном, чтобы избежать записи Class.Builder когда вам нужно создать новый экземпляр.

public class Person {
    private String attr1;
    private String attr2;
    private String attr3;

    // package access
    Person(PersonBuilder builder) {
        this.attr1 = builder.getAttr1();
        // ...
    }

    // ...
    // getters and setters 
}

public class PersonBuilder (
    private String attr1;
    private String attr2;
    private String attr3;

    // constructor with required attribute
    public PersonBuilder(String attr1) {
        this.attr1 = attr1;
    }

    public PersonBuilder setAttr2(String attr2) {
        this.attr2 = attr2;
        return this;
    }

    public PersonBuilder setAttr3(String attr3) {
        this.attr3 = attr3;
        return this;
    }

    public Person build() {
        return new Person(this);
    }
    // ....
}

Таким образом, вы можете использовать свой строитель следующим образом:

Person person = new PersonBuilder("attr1")
                            .setAttr2("attr2")
                            .build();

Недавно я начал читать «Эффективную Java» Джошуа Блоха. Я нашел идею шаблона Builder [Пункт 2 в книге] действительно интересным. Я попытался реализовать его в своем проекте, но были ошибки компиляции. Следующим по сути является то, что я пытался сделать:

Класс с несколькими атрибутами и его класс-строитель:

public class NutritionalFacts {
    private int sodium;
    private int fat;
    private int carbo;

    public class Builder {
        private int sodium;
        private int fat;
        private int carbo;

        public Builder(int s) {
            this.sodium = s;
        }

        public Builder fat(int f) {
            this.fat = f;
            return this;
        }

        public Builder carbo(int c) {
            this.carbo = c;
            return this;
        }

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

    private NutritionalFacts(Builder b) {
        this.sodium = b.sodium;
        this.fat = b.fat;
        this.carbo = b.carbo;
    }
}

Класс, где я пытаюсь использовать вышеуказанный класс:

public class Main {
    public static void main(String args[]) {
        NutritionalFacts n = 
            new NutritionalFacts.Builder(10).carbo(23).fat(1).build();
    }
}

Я получаю следующую ошибку компилятора:

вложенный экземпляр, который содержит effectivejava.BuilderPattern.NutritionalFacts.Builder требуется. NutritionalFacts n = new NutritionalFacts.Builder (10) .carbo (23) .fat (1) .build ();

Я не понимаю, что означает сообщение. Пожалуйста, объясни. Вышеприведенный код похож на пример, предложенный Блохом в его книге.


Вы должны объявить внутренний класс Builder static .

Проконсультируйтесь с некоторыми документами как для нестатических внутренних классов, так и для статических внутренних классов .

В принципе, нестатические экземпляры внутренних классов не могут существовать без прикрепленного экземпляра внешнего класса.


Вы пытаетесь получить нестатический класс статическим способом. Измените Builder на static class Builder и он должен работать.

Пример использования, который вы даете, терпит неудачу, потому что нет экземпляра Builder . Статический класс для всех практических целей всегда создается. Если вы не статируете, вам нужно сказать:

Widget = new Widget.Builder(10).setparm1(1).setparm2(3).build();

Потому что вам нужно будет каждый раз создавать новый Builder .


Класс Builder должен быть статичным. У меня нет времени, чтобы на самом деле проверить код за его пределами, но если он не работает, дайте мне знать, и я еще раз посмотрю.


Сделать строителем static класс. Тогда это сработает. Если он нестатический, для него потребуется экземпляр его собственного класса - и точка не должна иметь его экземпляр и даже запретить создание экземпляров без строителя.

public class NutritionFacts {
    public static class Builder {
    }
}

Ссылка: вложенные классы


Вы должны сделать класс Builder статическим, а также вы должны сделать поля окончательными и получить getters для получения этих значений. Не предоставляйте сеттерам эти значения. Таким образом, ваш класс будет совершенно непреложным.

public class NutritionalFacts {
    private final int sodium;
    private final int fat;
    private final int carbo;

    public int getSodium(){
        return sodium;
    }

    public int getfat(){
        return fat;
    }

    public int getCarbo(){
        return carbo;
    }

    public static class Builder {
        private int sodium;
        private int fat;
        private int carbo;

        public Builder sodium(int s) {
            this.sodium = s;
            return this;
        }

        public Builder fat(int f) {
            this.fat = f;
            return this;
        }

        public Builder carbo(int c) {
            this.carbo = c;
            return this;
        }

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

    private NutritionalFacts(Builder b) {
        this.sodium = b.sodium;
        this.fat = b.fat;
        this.carbo = b.carbo;
    }
}

И теперь вы можете установить свойства следующим образом:

NutritionalFacts n = new NutritionalFacts.Builder().sodium(10).carbo(15).
fat(5).build();







builder-pattern