Назад к вопросам
Middle
71
questionbank
Что такое паттерн проектирования 'строитель' (Builder)?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Паттерн "Строитель" (Builder) — это порождающий паттерн проектирования, предназначенный для создания сложных объектов пошагово. Он отделяет процесс конструирования сложного объекта от его представления так, что один и тот же процесс конструирования может создавать различные представления.
Принципы работы:
- Разделение: Отделяет логику создания объекта от самого объекта.
- Делегирование: Клиентский код (Director) делегирует создание объекта отдельному классу (Builder).
- Пошаговое создание: Объект собирается из составных частей с помощью набора методов строителя.
Основные участники:
- Product: Сложный объект, который мы хотим построить. Не зависит от процесса создания.
- Builder: Абстрактный интерфейс, определяющий шаги для построения Product.
- ConcreteBuilder: Конкретная реализация Builder, реализующая шаги построения и предоставляющая метод для получения готового Product.
- Director (Optional): Определяет порядок вызова шагов построения. Необязателен, клиентский код может напрямую взаимодействовать с ConcreteBuilder.
Преимущества:
- Позволяет создавать объекты с большим количеством необязательных параметров более читаемым образом, чем с помощью конструкторов с множеством аргументов или цепочек сеттеров.
- Позволяет создавать различные вариации одного и того же объекта, используя один и тот же процесс построения.
- Скрывает внутреннюю структуру создаваемого объекта.
Недостатки:
- Может увеличить количество классов в проекте (Builder, ConcreteBuilder, Product, Director).
Пример использования: Создание объекта класса Pizza с различными ингредиентами.
// Product
public class Pizza {
private String dough;
private String sauce;
private String cheese;
private List<String> toppings;
public void setDough(String dough) { this.dough = dough; }
public void setSauce(String sauce) { this.sauce = sauce; }
public void setCheese(String cheese) { this.cheese = cheese; }
public void setToppings(List<String> toppings) { this.toppings = toppings; }
@Override
public String toString() {
return "Pizza with dough=" + dough + ", sauce=" + sauce + ", cheese=" + cheese + ", toppings=" + toppings;
}
}
// Builder
public interface PizzaBuilder {
void buildDough();
void buildSauce();
void buildCheese();
void addTopping(String topping);
Pizza getPizza();
}
// ConcreteBuilder
public class MargheritaPizzaBuilder implements PizzaBuilder {
private Pizza pizza;
public MargheritaPizzaBuilder() {
this.pizza = new Pizza();
this.pizza.setToppings(new ArrayList<>()); // Инициализация списка
}
@Override
public void buildDough() {
pizza.setDough("Thin crust");
}
@Override
public void buildSauce() {
pizza.setSauce("Tomato sauce");
}
@Override
public void buildCheese() {
pizza.setCheese("Mozzarella");
}
@Override
public void addTopping(String topping) {
// Маргерита не добавляет топпинги, кроме базовых
}
@Override
public Pizza getPizza() {
return this.pizza;
}
}
// Director (Optional)
public class Kitchen {
private PizzaBuilder pizzaBuilder;
public void setPizzaBuilder(PizzaBuilder pb) {
pizzaBuilder = pb;
}
public Pizza getPizza() {
return pizzaBuilder.getPizza();
}
public void constructPizza() {
pizzaBuilder.buildDough();
pizzaBuilder.buildSauce();
pizzaBuilder.buildCheese();
// Могут быть вызваны другие методы, например addTopping() в другом билдере
}
}
Использование:
// Клиентский код
Kitchen kitchen = new Kitchen();
PizzaBuilder margheritaBuilder = new MargheritaPizzaBuilder();
kitchen.setPizzaBuilder(margheritaBuilder);
kitchen.constructPizza();
Pizza margherita = kitchen.getPizza();
System.out.println(margherita); // Вывод: Pizza with dough=Thin crust, sauce=Tomato sauce, cheese=Mozzarella, toppings=[]