Что такое Building?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Building (Паттерн Builder)
Определение
Builder (Строитель) — это порождающий паттерн проектирования, который позволяет пошагово конструировать сложные объекты. Паттерн отделяет конструирование объекта от его представления, так что в результате один и тот же процесс может выдавать различные представления объекта.
Задача, которую решает Builder
Основная проблема, которую решает Builder:
- Множество конструкторов — когда у объекта много опциональных параметров
- Нечитаемость кода — constructor(true, false, 5, null, "value", 123)
- Невозможность выставить параметры в любом порядке
- Создание неполных объектов с неправильными начальными значениями
// Плохо: множество конструкторов (Telescoping Constructor Anti-pattern)
public class User {
private String name;
private String email;
private int age;
private String phone;
private String address;
public User(String name) { ... }
public User(String name, String email) { ... }
public User(String name, String email, int age) { ... }
public User(String name, String email, int age, String phone) { ... }
public User(String name, String email, int age, String phone, String address) { ... }
// И еще 10 вариантов...
}
Классическая реализация Builder
public class User {
private final String name;
private final String email;
private final int age;
private final String phone;
private final String address;
// Приватный конструктор — нельзя создать через new
private User(UserBuilder builder) {
this.name = builder.name;
this.email = builder.email;
this.age = builder.age;
this.phone = builder.phone;
this.address = builder.address;
}
// Статический вложенный класс Builder
public static class UserBuilder {
private String name; // обязательный
private String email; // обязательный
private int age = 0; // опциональный с значением по умолчанию
private String phone = "";
private String address = "";
// Конструктор Builder принимает обязательные параметры
public UserBuilder(String name, String email) {
this.name = name;
this.email = email;
}
// Методы для установки опциональных параметров
public UserBuilder age(int age) {
this.age = age;
return this; // Возвращаем this для цепочки вызовов
}
public UserBuilder phone(String phone) {
this.phone = phone;
return this;
}
public UserBuilder address(String address) {
this.address = address;
return this;
}
// Метод для создания объекта User
public User build() {
return new User(this);
}
}
}
// Использование
public class Main {
public static void main(String[] args) {
User user = new User.UserBuilder("John", "john@example.com")
.age(30)
.phone("+1234567890")
.address("123 Main St")
.build();
// Или минимальный вариант
User user2 = new User.UserBuilder("Jane", "jane@example.com").build();
}
}
Преимущества Builder
1. Читаемость кода
// Понятно и самодокументируемо
User user = new User.UserBuilder("Alice", "alice@email.com")
.age(25)
.phone("+7900000000")
.address("Москва")
.build();
2. Гибкость параметров
- Можно выставлять параметры в любом порядке
- Не обязательно выставлять все параметры
- Легко добавлять новые параметры
3. Неизменяемость объектов
// После build() объект immutable (неизменяемый)
public final class ImmutableUser {
private final String name;
private ImmutableUser(UserBuilder builder) {
this.name = builder.name;
}
// Нет setters — нельзя изменить после создания
}
4. Валидация
public static class UserBuilder {
public User build() {
// Валидация перед созданием объекта
if (name == null || name.isEmpty()) {
throw new IllegalArgumentException("Name cannot be empty");
}
if (email == null || !email.contains("@")) {
throw new IllegalArgumentException("Invalid email");
}
if (age < 0 || age > 150) {
throw new IllegalArgumentException("Invalid age");
}
return new User(this);
}
}
Builder в Java стандартной библиотеке
StringBuilder и StringBuffer используют похожий подход:
// StringBuilder — не совсем классический Builder, но похож
String result = new StringBuilder()
.append("Hello")
.append(" ")
.append("World")
.toString();
// HttpRequest из Java 11+ (реальный Builder)
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
Builder с наследованием
Для иерархии классов можно использовать обобщенный Builder:
public abstract class AbstractUser {
protected String name;
protected String email;
protected AbstractUser(AbstractBuilder<?> builder) {
this.name = builder.name;
this.email = builder.email;
}
public static abstract class AbstractBuilder<T extends AbstractBuilder<T>> {
protected String name;
protected String email;
public T name(String name) {
this.name = name;
return self();
}
public T email(String email) {
this.email = email;
return self();
}
protected abstract T self();
public abstract AbstractUser build();
}
}
public class PremiumUser extends AbstractUser {
private String subscribedSince;
protected PremiumUser(PremiumUserBuilder builder) {
super(builder);
this.subscribedSince = builder.subscribedSince;
}
public static class PremiumUserBuilder extends AbstractBuilder<PremiumUserBuilder> {
private String subscribedSince;
public PremiumUserBuilder subscribedSince(String date) {
this.subscribedSince = date;
return this;
}
@Override
protected PremiumUserBuilder self() {
return this;
}
@Override
public PremiumUser build() {
return new PremiumUser(this);
}
}
}
Когда использовать Builder
- Когда много параметров — особенно опциональных (5+)
- Когда нужна неизменяемость — immutable объекты
- Когда сложный процесс создания — с валидацией и логикой
- Когда API должен быть понятным — самодокументируемый код
- Когда параметры часто меняются — легко расширять
Когда NOT использовать Builder
// Не нужен Builder для простого объекта
public class Point {
private int x;
private int y;
// Простого конструктора достаточно
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
Итоговый вывод
Builder — это элегантное решение для создания сложных объектов. Он делает код более читаемым, гибким и безопасным. Особенно полезен в API-дизайне и при работе с конфигурациями. В современной Java Builder встречается повсюду: от StringBuilder до HttpRequest и frameworkов вроде Spring.