1. Обзор
@Builder
проекта Lombok — это полезный механизм для использования шаблона Builder без написания шаблонного кода. Мы можем применить эту аннотацию к классу
или методу.
В этом кратком руководстве мы рассмотрим различные варианты использования @Builder
.
2. Зависимости Maven
Во-первых, нам нужно добавить Project Lombok в наш pom.xml
:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
Maven Central имеет последнюю версию Project Lombok здесь.
3. Использование @Builder
в классе
В первом случае мы просто реализуем Class
и хотим использовать конструктор для создания экземпляров нашего класса.
Первый и единственный шаг — добавить аннотацию к объявлению класса:
@Getter
@Builder
public class Widget {
private final String name;
private final int id;
}
Ломбок делает всю работу за нас. Теперь мы можем создать виджет
и протестировать его:
Widget testWidget = Widget.builder()
.name("foo")
.id(1)
.build();
assertThat(testWidget.getName())
.isEqualTo("foo");
assertThat(testWidget.getId())
.isEqualTo(1);
Если мы хотим создавать копии или почти копии объектов, мы можем добавить свойство toBuilder = true
в аннотацию @Builder
:
@Builder(toBuilder = true)
public class Widget {
//...
}
Это говорит Lombok добавить метод toBuilder()
в наш класс
. Когда мы вызываем метод toBuilder()
, он возвращает сборщик, инициализированный свойствами экземпляра, для которого он вызывается:
Widget testWidget = Widget.builder()
.name("foo")
.id(1)
.build();
Widget.WidgetBuilder widgetBuilder = testWidget.toBuilder();
Widget newWidget = widgetBuilder.id(2).build();
assertThat(newWidget.getName())
.isEqualTo("foo");
assertThat(newWidget.getId())
.isEqualTo(2);
В тестовом коде мы видим, что класс строителя, сгенерированный Lombok, назван так же, как и наш класс с добавленным к нему «Builder»
, в данном случае WidgetBuilder
.
Затем мы можем изменить нужные свойства и построить ()
новый экземпляр.
Если нам нужно указать обязательные поля, мы можем использовать конфигурацию аннотаций для создания вспомогательного построителя:
@Builder(builderMethodName = "internalBuilder")
public class RequiredFieldAnnotation {
@NonNull
private String name;
private String description;
public static RequiredFieldAnnotationBuilder builder(String name) {
return internalBuilder().name(name);
}
}
В этом случае мы скрываем сборщик по умолчанию как internalBuilder
и создаем
свой собственный. Таким образом, когда мы создаем билдер, мы должны указать требуемый параметр: ``
RequiredField.builder("NameField").description("Field Description").build();
Кроме того, чтобы убедиться, что наше поле существует, мы можем добавить аннотацию @NonNull
.
4. Использование @Builder
в методе
Предположим, мы используем объект, который хотим построить с помощью компоновщика, но не можем изменить исходный код или расширить класс .
Во-первых, давайте создадим быстрый пример, используя аннотацию Lombok @Value:
@Value
final class ImmutableClient {
private int id;
private String name;
}
Теперь у нас есть окончательный
класс
с двумя неизменяемыми членами, геттерами для них и конструктором со всеми аргументами.
Мы рассмотрели, как использовать @Builder
в классе
, но мы также можем использовать его в методах. Мы будем использовать эту возможность, чтобы обойти невозможность изменять или расширять ImmutableClient
.
Затем мы создадим новый класс с методом создания ImmutableClients:
class ClientBuilder {
@Builder(builderMethodName = "builder")
public static ImmutableClient newClient(int id, String name) {
return new ImmutableClient(id, name);
}
}
Эта аннотация создает метод с именем builder()
, который возвращает Builder
для создания ImmutableClients
.
Теперь создадим ImmutableClient
:
ImmutableClient testImmutableClient = ClientBuilder.builder()
.name("foo")
.id(1)
.build();
assertThat(testImmutableClient.getName())
.isEqualTo("foo");
assertThat(testImmutableClient.getId())
.isEqualTo(1);
5. Вывод
В этой краткой статье мы использовали аннотацию Lombok @Builder
для метода создания построителя для окончательного
класса
и узнали, как сделать некоторые поля класса
обязательными.
Образцы кода, как всегда, можно найти на GitHub .