Перейти к основному содержимому

Паттерн "Строитель" (Builder) в Java — сложная конфигурация без telescoping constructor

Разработчику Архитектору

Базовый обзор паттерна — в порождающих паттернах. Здесь — практический Builder на Java для объекта с множеством опциональных настроек.

Загрузка редактора схем…

Задача паттерна

Builder разделяет процесс создания сложного объекта и его представление. Вместо конструктора с длинным списком аргументов клиент задаёт параметры шагами через понятные методы.

Паттерн помогает в трёх случаях:

  • параметров много;
  • часть параметров опциональна;
  • объект должен остаться immutable после build().

Пример — HTTP-клиент с настройками

import java.util.HashMap;
import java.util.Map;

public final class HttpClient {
private final String baseUrl;
private final int connectTimeout;
private final int readTimeout;
private final Map<String, String> headers;
private final int maxRetries;

private HttpClient(Builder builder) {
this.baseUrl = builder.baseUrl;
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
this.headers = Map.copyOf(builder.headers);
this.maxRetries = builder.maxRetries;
}

public static final class Builder {
private final String baseUrl;
private int connectTimeout = 5_000;
private int readTimeout = 10_000;
private Map<String, String> headers = new HashMap<>();
private int maxRetries = 3;

public Builder(String baseUrl) {
this.baseUrl = baseUrl;
}

public Builder connectTimeout(int ms) {
this.connectTimeout = ms;
return this;
}

public Builder readTimeout(int ms) {
this.readTimeout = ms;
return this;
}

public Builder header(String key, String value) {
this.headers.put(key, value);
return this;
}

public Builder maxRetries(int retries) {
this.maxRetries = retries;
return this;
}

public HttpClient build() {
if (baseUrl == null || baseUrl.isBlank()) {
throw new IllegalArgumentException("baseUrl обязателен");
}
return new HttpClient(this);
}
}
}
HttpClient client = new HttpClient.Builder("https://api.example.com")
.connectTimeout(3_000)
.header("Authorization", "Bearer token")
.maxRetries(5)
.build();

Map.copyOf(...) в конструкторе защищает от случайной мутации заголовков после сборки.


Builder и конструктор

ПодходКогда подходит
Конструктор2-3 обязательных параметра, без множества опций
Builder4+ параметра, часть опциональна, нужен fluent API

Telescoping constructor (new X(a,b,c,d,e,...)) хуже читается и чаще даёт ошибки порядка аргументов.


Когда использовать

  • Конфигурации клиента API, подключения к БД, job-пайплайнов.
  • DTO/command-объекты с множеством опций.
  • immutable-модели, где нужна валидация перед созданием.

Риски и ограничения

Минус Builder — дублирование полей в Builder и в самом объекте.

Снижение шаблонного кода

В Java-проектах часто применяют Lombok @Builder, AutoValue или Immutables. Это ускоряет разработку, но не отменяет архитектурный выбор, когда Builder действительно нужен.


См. также

См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").