如果我将@Builder添加到类中.构建器方法已创建.
Person.builder().name("john").surname("Smith").build();
Run Code Online (Sandbox Code Playgroud)
我有一个要求需要特定字段的要求.在这种情况下,名称字段是必需的,但姓氏不是.理想情况下,我想宣布它是这样的.
Person.builder("john").surname("Smith").build()
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚如何做到这一点.我尝试将@Builder添加到构造函数中,但它不起作用.
@Builder
public Person(String name) {
this.name = name;
}
Run Code Online (Sandbox Code Playgroud)
Paw*_*wel 62
您可以使用Lombok注释配置轻松完成
import lombok.Builder;
import lombok.ToString;
@Builder(builderMethodName = "hiddenBuilder")
@ToString
public class Person {
private String name;
private String surname;
public static PersonBuilder builder(String name) {
return hiddenBuilder().name(name);
}
}
Run Code Online (Sandbox Code Playgroud)
然后就这样使用它
Person p = Person.builder("Name").surname("Surname").build();
System.out.println(p);
Run Code Online (Sandbox Code Playgroud)
当然@ToString
这里是可选的.
Ant*_*jev 30
我建议不要采用这种方法,因为你很难在其他对象上一致地应用它.相反,您只需使用@lombok.NonNull
注释标记字段,Lombok将在构造函数和设置器中为您生成空检查,因此Builder.build()
如果未设置这些字段,则会失败.
使用构建器模式可以非常清楚地标识要设置哪些值的字段.对于您的示例中的名称字段,这已经丢失,如果您正在构建具有多个必填字段的对象,则所有其他必填字段将进一步丢失.考虑以下示例,您能通过阅读代码来判断哪个字段是哪个?
Person.builder("John", "Michael", 16, 1987) // which is name, which is surname? what is 16?
.year(1982) // if this is year of birth, then what is 1987 above?
.build()
Run Code Online (Sandbox Code Playgroud)
The*_*ger 14
将Kevin Day的答案更进一步:
@Builder
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE) // If immutability is desired
@ToString
public class Person {
@NonNull // Presumably name cannot be null since its required by the builder
private final String name;
private final String surname;
private static PersonBuilder builder() {
return new PersonBuilder();
}
public static PersonBuilder builder(String name){
return builder().name(name);
}
}
Run Code Online (Sandbox Code Playgroud)
它并不理想,但它提供了编译时执行功能,此类的调用者将只使用一种构建器方法.
Kev*_*Day 13
这是另一种方法:
@Builder()
@Getter
@ToString
public class Person {
private final String name;
private final String surname;
public static PersonBuilder builder(String name){
return new PersonBuilder().name(name);
}
public static void main(String[] args) {
Person p = Person.builder("John Doe")
.surname("Bill")
.build();
}
}
Run Code Online (Sandbox Code Playgroud)
lil*_*nux 10
最简单的解决方案是将 a 添加@lombok.NonNull
到所有必需值。如果未设置必填字段,Builder 将无法构建对象。
这里有一个JUnit测试来证明的所有组合的行为final
和@NonNull
:
import static org.junit.Assert.fail;
import org.junit.Test;
import lombok.Builder;
import lombok.ToString;
public class BuilderTests {
@Test
public void allGiven() {
System.err.println(Foo.builder()
.nonFinalNull("has_value")
.nonFinalNonNull("has_value")
.finalNull("has_value")
.finalNonNull("has_value")
.build());
}
@Test
public void noneGiven() {
try {
System.err.println(Foo.builder()
.build()
.toString());
fail();
} catch (NullPointerException e) {
// expected
}
}
@Test
public void nonFinalNullOmitted() {
System.err.println(Foo.builder()
.nonFinalNonNull("has_value")
.finalNull("has_value")
.finalNonNull("has_value")
.build());
}
@Test
public void nonFinalNonNullOmitted() {
try {
System.err.println(Foo.builder()
.nonFinalNull("has_value")
.finalNull("has_value")
.finalNonNull("has_value")
.build());
fail();
} catch (NullPointerException e) {
// expected
}
}
@Test
public void finalNullOmitted() {
System.err.println(Foo.builder()
.nonFinalNull("has_value")
.nonFinalNonNull("has_value")
.finalNonNull("has_value")
.build());
}
@Test
public void finalNonNullOmitted() {
try {
System.err.println(Foo.builder()
.nonFinalNull("has_value")
.nonFinalNonNull("has_value")
.finalNull("has_value")
.build());
fail();
} catch (NullPointerException e) {
// expected
}
}
@Builder
@ToString
private static class Foo {
private String nonFinalNull;
@lombok.NonNull
private String nonFinalNonNull;
private final String finalNull;
@lombok.NonNull
private final String finalNonNull;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我解决问题的方法
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
@Data
@Builder(builderMethodName = "privateBuilder")
public class Person {
@NonNull
private String name;
@NonNull
private String surname;
private int age;//optional
public static Url safeBuilder() {
return new Builder();
}
interface Url {
Surname name(String name);
}
interface Surname {
Build surname(String surname);
}
interface Build {
Build age(int age);
Person build();
}
public static class Builder implements Url, Surname, Build {
PersonBuilder pb = Person.privateBuilder();
@Override
public Surname name(String name) {
pb.name(name);
return this;
}
@Override
public Build surname(String surname) {
pb.surname(surname);
return this;
}
@Override
public Build age(int age) {
pb.age(age);
return this;
}
@Override
public Person build() {
return pb.build();
}
}
}
Run Code Online (Sandbox Code Playgroud)
灵感来自这篇博文:
https://blog.jayway.com/2012/02/07/builder-pattern-with-a-twist/
归档时间: |
|
查看次数: |
41003 次 |
最近记录: |