У меня есть другой подход, использующий @Delegate
и Inner Class
, который поддерживает вычисленные значения для исключенных полей.
Во-первых, мы перемещаем поля, которые нужно исключить, в Inner Class
, чтобы Lombok не включил их в Builder.
Затем мы используем @Delegate
, чтобы открыть геттеры / сеттеры полей, исключенных построителем.
Пример:
@Builder
@Getter @Setter @ToString
class Person {
private String name;
private int value;
/* ... More builder-included fields here */
@Getter @Setter @ToString
private class BuilderIgnored {
private String position; // Not included in the Builder, and remain `null` until p.setPosition(...)
private String nickname; // Lazy initialized as `name+value`, but we can use setter to set a new value
/* ... More ignored fields here! ... */
public String getNickname(){ // Computed value for `nickname`
if(nickname == null){
nickname = name+value;
}
return nickname;
}
/* ... More computed fields' getters here! ... */
}
@Delegate @Getter(AccessLevel.NONE) // Delegate Lombok Getters/Setters and custom Getters
private final BuilderIgnored ignored = new BuilderIgnored();
}
За пределами этого Person
класса будет очевидно, что position
и nickname
на самом деле являются полями внутреннего класса.
Person p = Person.builder().name("Test").value(123).build();
System.out.println(p); // Person(name=Test, value=123, ignored=Person.BuilderIgnored(position=null, nickname=Test123))
p.setNickname("Hello World");
p.setPosition("Manager");
System.out.println(p); // Person(name=Test, value=123, ignored=Person.BuilderIgnored(position=Manager, nickname=Hello World))
Плюсы:
- Не заставляйте исключенные поля быть
final
- Поддержка вычисляемых значений для исключенных полей
- Разрешить вычисляемым полям ссылаться на любые поля, установленные построителем (другими словами, разрешить внутреннему классу быть нестатическим классом)
- Не нужно повторять список всех полей (например, перечисление всех полей, кроме исключенных, в конструкторе)
- Не отменять
@Builder
библиотеки Lombok (например, создание MyBuilder extends FooBuilder
)
Минусы:
- Исключенные поля на самом деле являются полями
Inner Class
; однако, используя идентификатор private
с соответствующими геттерами / сеттерами, вы можете имитировать, как если бы они были настоящими полями
- Следовательно, этот подход ограничивает доступ к исключенным полям с помощью Getters / Setters.
- Вычисленные значения инициализируются отложенным образом при вызове геттеров, а не при
.build()
.
person
Northnroro
schedule
18.01.2021