搜索插件以避免样板代码实现Joshua Bloch的builder pattern,我发现了令人惊叹的Lombok Project,它使您能够通过如下注释生成生成器:
onClick
如您所见,没有样板代码,您可以通过调用提供的静态@Builder
public class Person {
private String name;
private String address;
private String secondAddress;
}
PersonBuilder.builder().name("yourName").address("your Address").build();
方法轻松地创建Person
的实例,将类似于setter的调用链接起来就可以使用JavaBeans-Pattern并通过调用builder()
;
与构建器模式相比,JavaBeans-Pattern的缺点之一是(来自Effective Java):
由于构造被划分为多个调用,因此 JavaBean在构造期间可能处于不一致状态。
假设在上面的示例中,前两个属性(名称和地址)对于构造Person实例是必不可少的,则Lombok实现构建器模式的方式使开发人员能够拆分/缩短构造并可能build()
的实例不一致,例如:
Person
Joshua Bloch的解决方案更喜欢使用强制属性作为参数的构建器方法,这样就不可能将构造分为多个调用,如Item 2: Consider a builder when faced with many constructor parameters所示。
我的问题是: 是否有任何方便的方法,例如@Builder的注释参数或属性级别的Springs @Required或@Mandatory之类的方法,以强制Lombok避免像Joshua Bloch所建议的那样提供无参数的生成器构造函数并向构造函数提供强制性参数? >
我尝试了@Builder documentation中的许多选项,但找不到理想的解决方案。
对我有用的内容描述如下:
有点重复,可以避免。请参阅我的解决方案在约书亚·布洛赫(Joshua Bloch)的例子中的应用。
Person p = PersonBuilder.builder().name("yourName").build();
...
System.out.println(p.getAddress());
...
p.setAddress("your address");
答案 0 :(得分:4)
根据@Builder
docs,此注释可以与@NonNull
一起使用。如果标记为@NonNull
的字段为null
,您将得到NullPointerException
阻止创建无效对象:
@Builder
static class Person {
@NonNull
private final String name;
@NonNull
private final Integer age;
}
public static void main(String[] args) {
Person.builder()
.name("Fred")
.build(); // java.lang.NullPointerException: age is marked @NonNull but is null
}
要走得更远,您可以自己定义builder
方法。如果存在该方法,则Lombok不会生成它,您现在可以强制参数编译时间。
@Builder
static class Person {
@NonNull
private final String name;
@NonNull
private final Integer age;
public static PersonBuilder builder(String name, Integer age) {
return new PersonBuilder().name(name).age(age);
}
}
public static void main(String[] args) {
Person.builder("Fred", 11)
.build();
}
由于构建器类仍可访问,因此仍然可以通过编写new Person.PersonBuilder()
来创建构建器。
答案 1 :(得分:0)
此外,可以使用扩展名:
@Builder.Default <modifier><instanceVariable>=<default-value>
,
like:@Builder.Default private String myVariable = ""
。
请阅读:@Builder default properties
避免在某些情况下(如持久性,索引编制等)(在设置id或属性减少时,通过update / deleteBy / findBy进行设置,而没有完整的对象图),而不会要求某些属性设置的编译器错误。
这是一个优雅的解决方案,它不按建议覆盖 .build()或设置者。