← Назад к вопросам
Что такое паттерн Builder?
2.2 Middle🔥 122 комментариев
#Архитектура Flutter#ООП и паттерны
Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерн Builder
Builder — это паттерн проектирования, который позволяет пошагово конструировать сложные объекты. Вместо того чтобы передавать все параметры в конструктор, мы строим объект методом цепи вызовов.
Проблема, которую решает Builder
Без Builder (ПЛОХО)
class User {
final String name;
final String email;
final String? phone;
final String? address;
final int? age;
final bool emailVerified;
final bool phoneVerified;
final String? avatar;
final String? bio;
User(
this.name,
this.email,
this.phone,
this.address,
this.age,
this.emailVerified,
this.phoneVerified,
this.avatar,
this.bio,
);
}
// Использование — вспоминать порядок параметров сложно!
final user = User(
'John Doe',
'john@example.com',
'+1234567890',
null,
null,
true,
false,
null,
'Software Developer',
);
С Builder (ХОРОШО)
class User {
final String name;
final String email;
final String? phone;
final String? address;
final int? age;
final bool emailVerified;
final bool phoneVerified;
final String? avatar;
final String? bio;
const User({
required this.name,
required this.email,
this.phone,
this.address,
this.age,
this.emailVerified = false,
this.phoneVerified = false,
this.avatar,
this.bio,
});
}
// Использование — чётко, понятно!
final user = User(
name: 'John Doe',
email: 'john@example.com',
phone: '+1234567890',
emailVerified: true,
bio: 'Software Developer',
);
В Dart часто используют именованные параметры вместо классического Builder паттерна, но Builder всё ещё полезен в более сложных случаях.
Классический Builder паттерн
// Конечный объект
class HttpRequest {
final String url;
final String method;
final Map<String, String> headers;
final dynamic body;
final Duration timeout;
final bool followRedirects;
HttpRequest({
required this.url,
required this.method,
required this.headers,
required this.body,
required this.timeout,
required this.followRedirects,
});
@override
String toString() {
return 'HttpRequest(url: $url, method: $method, headers: $headers, body: $body, timeout: $timeout, followRedirects: $followRedirects)';
}
}
// Builder класс
class HttpRequestBuilder {
late String _url;
String _method = 'GET';
Map<String, String> _headers = {};
dynamic _body;
Duration _timeout = const Duration(seconds: 30);
bool _followRedirects = true;
// Setter методы, которые возвращают this для цепочки вызовов
HttpRequestBuilder url(String url) {
_url = url;
return this;
}
HttpRequestBuilder method(String method) {
_method = method;
return this;
}
HttpRequestBuilder header(String key, String value) {
_headers[key] = value;
return this;
}
HttpRequestBuilder headers(Map<String, String> headers) {
_headers.addAll(headers);
return this;
}
HttpRequestBuilder body(dynamic body) {
_body = body;
return this;
}
HttpRequestBuilder timeout(Duration timeout) {
_timeout = timeout;
return this;
}
HttpRequestBuilder followRedirects(bool value) {
_followRedirects = value;
return this;
}
// Финальный метод, который создаёт объект
HttpRequest build() {
if (_url.isEmpty) {
throw ArgumentError('URL is required');
}
return HttpRequest(
url: _url,
method: _method,
headers: _headers,
body: _body,
timeout: _timeout,
followRedirects: _followRedirects,
);
}
}
// Использование
final request = HttpRequestBuilder()
.url('https://api.example.com/users')
.method('POST')
.header('Content-Type', 'application/json')
.header('Authorization', 'Bearer token')
.body('{"name": "John"}')
.timeout(const Duration(seconds: 60))
.build();
print(request);
Builder для сложных UI элементов
// Класс для конфигурации кнопки
class ButtonConfig {
final String label;
final VoidCallback onPressed;
final ButtonStyle? style;
final Color? backgroundColor;
final Color? textColor;
final double? width;
final double? height;
final EdgeInsets padding;
final BorderRadius borderRadius;
final double fontSize;
final FontWeight fontWeight;
const ButtonConfig({
required this.label,
required this.onPressed,
this.style,
this.backgroundColor,
this.textColor,
this.width,
this.height,
this.padding = const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
this.borderRadius = const BorderRadius.all(Radius.circular(8)),
this.fontSize = 16,
this.fontWeight = FontWeight.w600,
});
}
// Builder для кнопки
class CustomButtonBuilder {
late String _label;
late VoidCallback _onPressed;
Color? _backgroundColor;
Color? _textColor;
double? _width;
double? _height;
EdgeInsets _padding = const EdgeInsets.symmetric(horizontal: 16, vertical: 12);
BorderRadius _borderRadius = const BorderRadius.all(Radius.circular(8));
double _fontSize = 16;
FontWeight _fontWeight = FontWeight.w600;
CustomButtonBuilder label(String label) {
_label = label;
return this;
}
CustomButtonBuilder onPressed(VoidCallback callback) {
_onPressed = callback;
return this;
}
CustomButtonBuilder backgroundColor(Color color) {
_backgroundColor = color;
return this;
}
CustomButtonBuilder textColor(Color color) {
_textColor = color;
return this;
}
CustomButtonBuilder size(double width, double height) {
_width = width;
_height = height;
return this;
}
CustomButtonBuilder padding(EdgeInsets padding) {
_padding = padding;
return this;
}
CustomButtonBuilder borderRadius(BorderRadius radius) {
_borderRadius = radius;
return this;
}
CustomButtonBuilder fontSize(double size) {
_fontSize = size;
return this;
}
ButtonConfig build() {
return ButtonConfig(
label: _label,
onPressed: _onPressed,
backgroundColor: _backgroundColor,
textColor: _textColor,
width: _width,
height: _height,
padding: _padding,
borderRadius: _borderRadius,
fontSize: _fontSize,
fontWeight: _fontWeight,
);
}
}
// Использование в Flutter
final buttonConfig = CustomButtonBuilder()
.label('Click me')
.onPressed(() => print('Clicked!'))
.backgroundColor(Colors.blue)
.textColor(Colors.white)
.size(200, 50)
.fontSize(18)
.build();
Преимущества Builder
- Читаемость — понятно, что делается на каждом шаге
- Гибкость — легко добавлять новые опции
- Валидация — можно проверять данные в build()
- Повторное использование — builder можно переиспользовать
- Неизменяемость — создаёт immutable объекты
Builder vs Конструктор с параметрами
Конструктор — когда мало параметров (до 3-4)
User(name: 'John', email: 'john@example.com')
Builder — когда много параметров или сложная логика
UserBuilder()
.name('John')
.email('john@example.com')
.phone('+123')
.address('Some Address')
.build()
В Dart часто используют именованные параметры вместо Builder для простых случаев, но Builder остаётся полезен для более сложных объектов с валидацией.
Builder паттерн — это классическое решение для создания сложных объектов с множеством параметров.