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

Взгляните на следующий код. У нас есть класс Simple Pizza, который имеет некоторые свойства (Также известное как состояние, которое представляет инициализированный объект.) и для простоты имеет одно поведение (Также известный как метод) Display(), который выводит ингредиенты пиццы.

Теперь в нашем клиенте, если один из наших разработчиков хочет создать новую пиццу, скажите Margherita. Разработчик должен будет сделать что-то вроде следующего кода.

Ваша первая мысль может заключаться в том, что выглядит хорошо! именно так мы предполагаем инициализировать объект. Но попробуйте представить, что нашим разработчикам нужно создать точный объект в нескольких местах нашего приложения. Этот основной процесс инициализации становится церемонией. А также разработчик должен правильно отслеживать все свойства.

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

Переходя к шаблону проектирования Builder, нам понадобятся следующие компоненты:

  1. Директор — PizzaMaker
  2. ConcreteBuilder — Margherita, ClassicChicken и др.
  3. Строитель(аннотация) — PizzaBuilder
  4. Продукт — Пицца

Для нашего продукта у нас уже есть класс Pizza выше.

Далее, давайте создадим класс Builder, класс Builder — это абстрактный класс, который указывает, что ConcreteBuilder должен следовать, чтобы установить представление продукта. Мы называем наш класс Builder как PizzaBuilder, код выглядит следующим образом:

Класс PizzaBuilder имеет метод GetResult(), который возвращает инициализированную Pizza в наш класс PizzaMaker (мы скоро рассмотрим класс PizzaMaker). Внутри метода GetResult() мы вызываем другие методы класса PizzaBuilder, такие как SetBase() , IsPizzaHandTosted() и так далее по порядку. Эти внутренние методы устанавливают свойства Pizza, при этом каждый метод отвечает только за установку связанных свойств.

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

Теперь давайте взглянем на компонент Director, который отвечает за возврат конечного объекта клиенту. Директор использует класс Builder.

Ничего особенного в PizzaMaker не происходит. У него есть метод Construct, который просто перенаправляет вызов метода ConcreteBuilders GetResult() (В нашем случае это будет пицца Margherita, ClassicChicken или любая конкретная пицца, которую мы создаем). Таким образом, Директор берет ConcreteBuilder, который является производным от Строителя через его конструктор.

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

Приведенный выше класс реализует класс PizzaBuilder и его методы. Я инициализировал тип Pizza в конструкторе. А в методе GetResult() вызвали методы, отвечающие за установку состояния инициализированного типа Pizza поштучно, и в итоге вернули пиццу.

Примечание. MeatType, BaseType и CheeseType — это перечисления, которые я здесь не включил, вы найдете полное решение в моем репозитории github.

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

В нашем клиенте мы создаем новый PizzaMaker [Компонент директора] и передаем его конструктору класс New Margherita (компонент ConcreteBuilder), а затем вызываем метод Construct() в Pizzamaker, который возвращает нам ожидаемый PizzaType. А затем мы просто вызываем поведение типа пиццы, которое хотим, в нашем случае это просто метод Display().

Прежде чем я закончу эту статью, я хочу, чтобы вы прочитали определение шаблона проектирования «Строитель», изложенное в книге «Банда четырех»:

«Отделяет построение сложных объектов от их представления. Так что один и тот же процесс строительства может создавать разные представления».

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