Паттерн Builder
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy. Урок 67 из 87.
Builder Pattern — это порождающий шаблон проектирования, который решает распространённую проблему: создание сложных объектов с множеством необязательных параметров. Вместо создания нескольких конструкторов или передачи null для неиспользуемых параметров Builder позволяет создавать объекты пошагово.
Рассмотрим создание объекта User с обязательными полями (name, email) и необязательными (age, phone, address). Без Builder вам пришлось бы использовать телескопические конструкторы или громоздкий конструктор с множеством параметров. Паттерн Builder предлагает более чистый подход:
public class User {
private final String name; // обязательный
private final String email; // обязательный
private final int age; // необязательный
private final String phone; // необязательный
private User(UserBuilder builder) {
this.name = builder.name;
this.email = builder.email;
this.age = builder.age;
this.phone = builder.phone;
}
public static class UserBuilder {
private final String name;
private final String email;
private int age;
private String phone;
public UserBuilder(String name, String email) {
this.name = name;
this.email = email;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public User build() {
return new User(this);
}
}
}Методы Builder возвращают this, обеспечивая цепочку вызовов методов: плавный и удобный для чтения способ создавать объекты:
User user = new User.UserBuilder("Alice", "alice@email.com")
.age(25)
.phone("555-1234")
.build();Обратите внимание, что User constructor является private: объекты можно создавать только через Builder. Этот паттерн особенно полезен, когда у объектов много optional fields, поскольку он делает ваш код более читаемым и менее подверженным ошибкам, чем длинные списки parameter.
Задание
ЛегкоДавайте создадим систему заказа пиццы с использованием шаблона Builder! Вместо работы с constructor, который принимает десятки parameter для всех возможных начинок и опций, вы создадите fluent builder, благодаря которому настройка пиццы будет простой и понятной.
Вы организуете код в двух файлах:
Pizza.java: СоздайтеPizzaclass, который использует шаблон Builder для создания объектов. В вашей пицце должны быть следующие fields:size(String) — обязательное поле, обозначает размер пиццыcheese(boolean) — необязательное поле, по умолчанию имеет значение falsepepperoni(boolean) — необязательное поле, по умолчанию имеет значение falsemushrooms(boolean) — необязательное поле, по умолчанию имеет значение falseconstructor
Pizzaдолжен быть private и принимать толькоPizzaBuilderв качестве parameter, копируя все значения из builder в fields пиццы.Добавьте method
getDescription(), который возвращает string в следующем формате:[size] Pizza with: [toppings], где toppings — это разделённый запятыми список toppings, имеющих значение true (Cheese, Pepperoni, Mushrooms). Если toppings не выбраны, часть с toppings должна содержать толькоno toppings.Создайте static inner class
PizzaBuilder, содержащий:- constructor, принимающий обязательный parameter
size - methods
cheese(),pepperoni()иmushrooms(), каждый из которых устанавливает соответствующее boolean-значение в true и возвращаетthisдля цепочки вызовов - method
build(), который возвращает новуюPizza
- constructor, принимающий обязательный parameter
Main.java: Продемонстрируйте работу builder для пиццы! Вы получите четыре inputs: размер пиццы (String) и три значения yes/no (Strings), указывающие, нужно ли соответственно добавить cheese, pepperoni и mushrooms.Создайте
PizzaBuilderс указанным размером. Затем, основываясь на каждом input yes/no, вызовите в цепочке соответствующие methods для toppings. Если input равен"yes", вызовите method этой topping; если"no", пропустите его. Наконец, вызовитеbuild(), чтобы создать пиццу.Выведите результат вызова
getDescription()для созданной пиццы.
Вы получите четыре inputs по порядку: size (String), add cheese (String: "yes" или "no"), add pepperoni (String: "yes" или "no"), add mushrooms (String: "yes" или "no").
Например, для inputs Large, yes, no, yes результатом будет: Large Pizza with: Cheese, Mushrooms
Обратите внимание, как шаблон Builder позволяет создавать пиццы с любой комбинацией toppings без необходимости создавать отдельные constructors для каждого варианта!
Попробуйте сами
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Считать входные данные
String size = scanner.nextLine();
String addCheese = scanner.nextLine();
String addPepperoni = scanner.nextLine();
String addMushrooms = scanner.nextLine();
// TODO: Создать PizzaBuilder с заданным размером
// TODO: Вызвать методы топпингов цепочкой на основе вводов yes/no
// TODO: Собрать пиццу и вывести её описание
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово thisМетодыПоля (атрибуты)Метод-конструкторПерегрузка конструкторовИтоги — Простой калькулятор4Наследование
Основы наследования (extends)Ключевое слово superПереопределение методов (@Override)Цепочка конструкторовКласс ObjectОдиночное и многоуровневое наследованиеПочему нет множественного наследования классовИтоги — Иерархия сотрудников7Специальные методы и класс Object
Метод toString()equals() и hashCode()Метод clone()compareTo() и ComparableИнтерфейс ComparatorПовторение — Кастомная сортировка2Модификаторы доступа и инкапсуляция
Обзор уровней доступаМетоды геттеры и сеттерыСокрытие данныхКлючевое слово finalИтоги — Менеджер банковского счета5Полиморфизм
Основы перегрузки методовПереопределение методов (Run-Time)Upcasting и DowncastingОператор instanceofАбстрактные классы и методыИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияАгрегация против композицииВнутренние, вложенные и анонимные классыEnums и методы перечисленийRecords (Java 16+)Sealed-классы (Java 17+)11Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy3Свойства класса и статические члены
Переменные экземпляра и статические переменныеСтатические методыСтатические блокиКонстанты (static final)Итоги: Счетчик и утилиты6Интерфейсы и абстрактные классы
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовDefault и Static методы в интерфейсахАбстрактные классы vs ИнтерфейсыФункциональные интерфейсыИтоги — Платежная система9Обобщения
Введение в обобщенияОбобщенные классыОбобщенные методыОграниченные параметры типаСимволы подстановки (Wildcards: ?, extends, super)Итоги — Обобщенный контейнер12Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Итератор»Потренируйтесь самостоятельно: Онлайн-компилятор Java