Паттерн Builder для продвинутых
Начав обсуждать билдер, остановиться сложно. Я и не буду:) Сегодня подсвечу пару интересных моментов и один приём, который точно пригодится на практике.
Сразу к делу:
1️⃣ Билдер может содержать сложную логику, а не просто копить будущие поля
Например:
🔸 Собирать одну информацию, отдавать объекту другую
🔸 Возвращать любые классы и объекты, даже прокси и уже созданные
🔸 Проводить операции внутри метода
Всё это при умелом использовании создаёт симпатичное и лаконичное API.
Пример 1: класс
Гораздо интереснее, чем кажется:
▫️ Копит данные в изменяемом массиве, на выходе отдаёт неизменяемую строку
▫️ Методы
▫️ Есть дополнительные методы вроде
В результате получаем удобный и функциональный класс. Ломбок такой билдер не соберёт, чатЖПТ такое не придумает:)
Пример 2: класс HttpClient
В самом простом варианте код выглядит так:
🤔 Зачем тут билдер? Почему просто не сделать new HttpClient()?
Потому что внутри build происходит такая магия:
Тут прячется установка работы с сетью в 200+ строк кода и механизм по завершению работы с сетью, когда объект HttpClient станет не нужен. Хотя объект работает с ресурсами, его не надо помещать в блок
Мелочь, а приятно🥰
И вторая классная особенность:
2️⃣ Билдер может сделать несколько объектов на базе переданных данных
Часто помогает при написании тестов.
Пример: тестируем работу с классом Account, в котором много полей. Можно в каждом тесте создавать тестовые объекты с нуля и копипастить километр кода. Или поступить иначе:
▫️ Сделать общий для всех тестов билдер, но build() не вызывать
▫️ В каждом тесте доставить нужные поля и построить новый объект
Получается так:
Это короче, чем в каждом тесте создавать объект с нуля. Плюс сразу видно "главное" для теста поле.
Приём подходит не всегда, но иногда здорово улучшает читаемость.
Итого
✅ Метод
✅ Builder может создать несколько объектов на основе переданных данных
Возьмите эти свойства на заметку, в умелых руках паттерн Builder делает код проще и удобнее🔥
Начав обсуждать билдер, остановиться сложно. Я и не буду:) Сегодня подсвечу пару интересных моментов и один приём, который точно пригодится на практике.
Сразу к делу:
1️⃣ Билдер может содержать сложную логику, а не просто копить будущие поля
Например:
🔸 Собирать одну информацию, отдавать объекту другую
🔸 Возвращать любые классы и объекты, даже прокси и уже созданные
🔸 Проводить операции внутри метода
build
Всё это при умелом использовании создаёт симпатичное и лаконичное API.
Пример 1: класс
StringBuilder
Гораздо интереснее, чем кажется:
▫️ Копит данные в изменяемом массиве, на выходе отдаёт неизменяемую строку
▫️ Методы
append
можно вызывать сколько угодно раз▫️ Есть дополнительные методы вроде
reverse
или delete
В результате получаем удобный и функциональный класс. Ломбок такой билдер не соберёт, чатЖПТ такое не придумает:)
Пример 2: класс HttpClient
В самом простом варианте код выглядит так:
HttpClient client = HttpClient.newBuilder().build();
🤔 Зачем тут билдер? Почему просто не сделать new HttpClient()?
Потому что внутри build происходит такая магия:
SingleFacadeFactory facadeFactory = new SingleFacadeFactory();
HttpClientImpl impl = new HttpClientImpl(builder, facadeFactory);
impl.start();
…
return facadeFactory.facade;
Тут прячется установка работы с сетью в 200+ строк кода и механизм по завершению работы с сетью, когда объект HttpClient станет не нужен. Хотя объект работает с ресурсами, его не надо помещать в блок
try-with-resources
.Мелочь, а приятно🥰
И вторая классная особенность:
2️⃣ Билдер может сделать несколько объектов на базе переданных данных
Часто помогает при написании тестов.
Пример: тестируем работу с классом Account, в котором много полей. Можно в каждом тесте создавать тестовые объекты с нуля и копипастить километр кода. Или поступить иначе:
▫️ Сделать общий для всех тестов билдер, но build() не вызывать
▫️ В каждом тесте доставить нужные поля и построить новый объект
Получается так:
// общее поле c базовой информацией
Account.Builder accBuilder = Account.builder().INN(…).KPP(…)
// в тесте, где важен БИК:
Account acc = accBuilder.RCBIC(123).build();
// в тесте, где нужно название банка
Acccount acc = accBuilder.bankName("green").build();
Это короче, чем в каждом тесте создавать объект с нуля. Плюс сразу видно "главное" для теста поле.
Приём подходит не всегда, но иногда здорово улучшает читаемость.
Итого
✅ Метод
build
может содержать сложную логику: от проверки параметров до шифрований и преобразований✅ Builder может создать несколько объектов на основе переданных данных
Возьмите эти свойства на заметку, в умелых руках паттерн Builder делает код проще и удобнее🔥