Шаблон проектирования строителя

Шаблон проектирования Builder — это классический шаблон проектирования Gang of Four Creation. В отличие от паттерна Pattern Design, Builder Design Pattern решает проблемы с созданием объектов из-за сложных конструкторов.

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

При создании объектов такого класса нам необходимо ознакомиться с документацией по классу, чтобы понять порядок параметра и необходимость отправки null в случае необязательного параметра.

Другой вариант — создать несколько конструкторов с необходимыми параметрами. Но этот подход не является действительно масштабируемым, когда задействовано много параметров. Шаблон проектирования Builder также очень полезен при создании неизменяемого объекта.

Шаблон Builder решает проблему с большим количеством необязательных параметров и несогласованным состоянием, предоставляя способ пошагового построения объекта и предоставляя метод, который фактически возвращает окончательный объект. Процесс создания объекта является общим, поэтому его можно использовать для создания различных представлений одного и того же объекта.

Шаблон проектирования построителя использует цепочку методов для реализации методов построителя.

Связывание методов используется для вызова нескольких методов для одного и того же объекта, который выполняется как один оператор. Цепочка методов реализована рядом методов, которые возвращают ссылку this для экземпляра класса.

Поскольку возвращаемые значения методов в цепочке являются этой ссылкой, эта реализация позволяет нам вызывать методы в цепочке, вызывая следующий метод для возвращаемого значения предыдущего метода в цепочке.

Это руководство является частью серии Creational Design Pattern. Взгляните на другие шаблоны креативного дизайна:

  1. Singleton Creational Design Pattern Java: объяснение [6 примеров кода]
  2. Factory Design Pattern Java Simplified [Простой пример из реальной жизни]
  3. Простые подробные примеры фабричного метода проектирования Java
  4. Пример абстрактного фабричного проектирования Java в реальном мире
  5. Реальный пример шаблона проектирования Builder на Java
  6. Прототип шаблона проектирования Java, пример реального мира

Когда использовать шаблон проектирования Builder?

  1. Шаблон Builder следует использовать всякий раз, когда задействован сложный конструктор.
  2. Когда Object нужно мне сделать в шагах.
  3. Когда нам нужно создать неизменяемый класс.
  4. Когда нам нужно создать объект с несколькими необязательными параметрами.

Реализация шаблона проектирования Builder

  1. Создайте внешний класс только с аргументами. Нет необходимости создавать какие-либо общедоступные конструкторы и методы установки/получения.
  2. Создайте статический вложенный класс, а затем скопируйте все аргументы из внешнего класса в класс Builder. Мы должны следовать соглашению об именах, и если имя класса — Student, то класс строителя должен называться StudentBuilder.
  3. Класс Builder должен иметь общедоступный конструктор со всеми обязательными/обязательными атрибутами в качестве параметров.
    Класс Builder должен иметь методы для установки необязательных параметров, и он должен возвращать тот же объект Builder после установки необязательного атрибута.
  4. Последним шагом является предоставление метода build() в классе построителя, который будет возвращать объект внешнего класса, необходимый клиентской программе. Для этого нам нужен частный конструктор во внешнем классе с объектом класса Builder в качестве аргумента.

Пример шаблона проектирования Builder в реальном мире

Рассмотрим сценарий, в котором у клиента есть сертификационный веб-сайт, и он хочет запросить у студентов их личную информацию. Студенту предоставляется форма с несколькими вопросами, из которых обязательными являются только имя и фамилия.

Клиент хочет сохранить эту информацию в неизменном объекте. Мы можем сохранить эту информацию, напрямую вызвав конструктор, но в форме достаточно вопросов, и студент может выбрать ответ только на некоторые из них.

Нецелесообразно создавать конструктор с различными комбинациями. Это идеальный сценарий для использования шаблона проектирования Builder.

Класс продукта

Класс Student — это наш класс продукта, и он имеет статический внутренний класс StudentBuilder.

package com.adevguide.java.designpatterns.builder;

public class Student {

    private String firstName; // mandatory
    private String lastName; // mandatory
    private String age; // optional
    private String gender; // optional
    private boolean isGraduate; // optional
    private boolean hasExperience; // optional
    private String city; // optional
    private String state; // optional
    private boolean isEarning; // optional

    private Student(StudentBuilder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.age = builder.age;
        this.gender = builder.gender;
        this.isGraduate = builder.isGraduate;
        this.hasExperience = builder.hasExperience;
        this.city = builder.city;
        this.state = builder.state;
        this.isEarning = builder.isEarning;
    }

    @Override
    public String toString() {
        return " firstName=" + firstName + "\n lastName=" + lastName + "\n age=" + age + "\n gender=" + gender
                + "\n isGraduate=" + isGraduate + "\n hasExperience=" + hasExperience + "\n city=" + city + "\n state="
                + state + "\n isEarning=" + isEarning;
    }

    public static class StudentBuilder {

        private String firstName;
        private String lastName;
        private String age;
        private String gender;
        private boolean isGraduate;
        private boolean hasExperience;
        private String city;
        private String state;
        private boolean isEarning;

        public StudentBuilder(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public StudentBuilder addAge(String age) {
            this.age = age;
            return this;
        }

        public StudentBuilder addGender(String gender) {
            this.gender = gender;
            return this;
        }

        public StudentBuilder addisGraduate(boolean isGraduate) {
            this.isGraduate = isGraduate;
            return this;
        }

        public StudentBuilder addHasExperience(boolean hasExperience) {
            this.hasExperience = hasExperience;
            return this;
        }

        public StudentBuilder addCity(String city) {
            this.city = city;
            return this;
        }

        public StudentBuilder addState(String state) {
            this.state = state;
            return this;
        }

        public StudentBuilder addIsEarning(boolean isEarning) {
            this.isEarning = isEarning;
            return this;
        }

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

    }

}

Внешний класс Student имеет один частный конструктор Student(StudentBuilder builder), который принимает объект построителя, а затем инициализирует параметры класса.

Статический внутренний класс StudentBuilder имеет один общедоступный конструктор с обязательными параметрами в качестве аргументов. Это не обязательно, мы всегда можем создать конструктор без аргументов и передавать обязательные параметры через метод в качестве необязательных параметров.

Статический внутренний класс имеет отдельные методы для каждого из необязательных параметров, которые будут устанавливать значение параметра в объекте и возвращать экземпляр объекта.

Наконец, требуется общедоступный метод build(), он вызовет частный конструктор внешнего класса, передаст ему экземпляр класса-строителя и вернет экземпляр внешнего класса.

Класс клиента

package com.adevguide.java.designpatterns.builder;

/**
 * @author PraBhu
 *
 */
public class Client {

    public static void main(String[] args) {

        Student student = new Student.StudentBuilder("Pra", "Bhu") // mandatory parameters
                .addAge("25") // optional
                .addGender("M") // optional
                .addHasExperience(true) // optional
                .build(); // to get back student option

        System.out.println(student);

    }

}

firstName=Pra
lastName=Bhu
age=25
gender=M
isGraduate=false
hasExperience=true
city=null
state=null
isEarning=false

Преимущества дизайна Builder Pattern

  • Он обеспечивает четкое разделение между построением и представлением объекта.
  • неизменность принудительно применяется к объекту после его создания.
  • Код создания объекта менее подвержен ошибкам, поскольку пользователь будет знать, что он передает, благодаря явному вызову метода.
  • Шаблон Builder повышает надежность, так как клиенту будет доступен только полностью построенный объект.

Подводные камни шаблона проектирования Builder

  • Шаблон Builder многословен и требует дублирования кода, поскольку Builder должен скопировать все поля из исходного/внешнего класса.

Пример шаблона проектирования Builder

  • java.lang.StringBuilder#append()
  • java.nio.ByteBuffer#put() (также в CharBuffer, ShortBuffer, IntBuffer, LongBuffer, FloatBuffer и DoubleBuffer)
  • java.lang.StringBuffer#append()
  • javax.swing.GroupLayout.Group#addComponent()

Исходный код шаблона проектирования Builder

Исходный код, использованный в этом руководстве, можно найти на GitHub.

использованная литература

https://medium.com/@ajinkyabadve/builder-design-patterns-in-java-1ffb12648850

Первоначально опубликовано на https://www.adevguide.com 3 сентября 2019 г.