Ara*_*gir 5 java builder lombok
搜索插件以避免样板代码来实现Joshua Bloch的构建器模式,我发现了令人惊叹的Lombok 项目,它使您能够通过这样的注释生成构建器:
@Builder
public class Person {
private String name;
private String address;
private String secondAddress;
}
PersonBuilder.builder().name("yourName").address("your Address").build();
Run Code Online (Sandbox Code Playgroud)
如您所见,没有样板代码,您可以Person通过调用提供的静态builder()方法轻松创建一个实例,链接 setter-like-calls 就像它与 JavaBeans-Pattern 一起工作一样,并以调用结束链build();
与构建器模式相比,JavaBeans-Pattern 的缺点之一是(来自Effective Java):
由于构造被拆分为多个调用,因此JavaBean 在其构造过程中可能处于不一致的状态。
假设在上面的示例中,前两个属性 name 和 address 是构造 Person 实例所必需的,Lombok 实现构建器模式的方式使开发人员能够拆分/缩短构造并使用可能不一致的实例执行某些操作Person, 像这样:
Person p = PersonBuilder.builder().name("yourName").build();
...
System.out.println(p.getAddress());
...
p.setAddress("your address");
Run Code Online (Sandbox Code Playgroud)
Joshua Bloch的解决方案更喜欢使用强制属性作为参数的构建器方法,这样就不可能将构造拆分到多个调用中,如第 2 条:当面对许多构造函数参数时考虑构建器。
我的问题是: 是否有任何方便的方法,例如 @Builder 的注释参数或属性级别上的 Springs @Required 或 @Mandatory 之类的东西,以强制 Lombok 避免提供无参数的构建器构造函数并提供具有强制参数的构造函数,如 Joshua Bloch提议?
我尝试了@Builder 文档中的许多选项,但找不到理想的解决方案。
对我有用的描述如下:
这有点像样板,这是可以避免的。请参阅我在 Joshua Bloch 的示例中应用的解决方案。
/**
* Uncle Bobs builder example for constructors with many required & optional parameters,
* realized by lombok.
*
*/
@AllArgsConstructor(access=AccessLevel.PRIVATE) // Let lombok generate private c-tor with all parameters, as needed by @Builder.
@Builder(
builderClassName="Builder", // Cosmetic. Without this option, the builder class would have the name NutritionFactsBuilder.
toBuilder=true // Enabling creation of a builder instance based on a main class instance: NutritionFacts.
)
public class NutritionFacts {
// Required parameters
private int servingSize;
private int servings;
// Optional parameters
private int calories;
private int fat;
private int sodium;
private int carbohydrate;
/**
* A builder method demanding required parameters.
*/
public static Builder builder(int servingSize, int servings) {
return new NutritionFacts(servingSize, servings).toBuilder();
}
/**
* eclipse-created C-tor with required parameters.
* Can be public for instantiating, but doesn't have to.
*/
public NutritionFacts(int servingSize, int servings) {
super();
this.servingSize = servingSize;
this.servings = servings;
}
public static void main(String[] args) {
NutritionFacts cocaCola = NutritionFacts.builder(240, 8)
.calories(100)
.sodium(35)
.carbohydrate(27)
.build();
}
}
Run Code Online (Sandbox Code Playgroud)
根据@Builder文档,此注释可以与@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
}
Run Code Online (Sandbox Code Playgroud)
要更进一步,您可以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();
}
Run Code Online (Sandbox Code Playgroud)
但是,仍然可以通过编写来创建构建器,new Person.PersonBuilder()因为构建器类仍然可以访问。
另外,在扩展中可以使用:
@Builder.Default <modifier><instanceVariable>=<default-value>,
喜欢:@Builder.Default private String myVariable = ""。
请阅读:@Builder 默认属性
避免编译器错误询问在某些情况下不会设置的必需属性,例如持久性、索引等(从 id 或减少的属性集更新/deleteBy/findBy,没有完整的对象图)。
这是一个优雅的解决方案,不会按照建议重写.build()或setter。
| 归档时间: |
|
| 查看次数: |
5650 次 |
| 最近记录: |