java builder 模式
在effactive java上看到说当构造方法参数过多时使用builder模式,然后发现提供的set模板的Builder只需要return this。所以想了解一下细节以及差异。
JavaBeans模式本身有严重的缺陷。由于构造方法被分割成多次调用,所以在构造过程中JavaBean可能处于不一致状态。该类仅有通过检查构造函数参数的有效性,而没有强制的一致性措施。在不一致的状态下尝试使用对象可能导致一些错误,这些错误与平时代码的BUG很是不同,因此很难调试。一个相关的缺点是,javaBeans模式排除了让类不可变的可能性,并且需要程序员增加工作以确保线程安全。
在使用javaBean的时候,尤其是多线程获取的时候,几个线程对同一个javaBean操作:
线程A:对对象进行set操作。
线程B:对对象进行get操作。
这就会出现一种情况,线程A没有set完线程B就开始去相应属性。
Builder 模式
不直接构造所需的对象,而是调用一个包含所有必需参数的构造方法(或静态工厂)得到一个builder对象,然后设置可选参数,最后通过builder对象的一个无参builder方法来生成对象,该对象通常是不可变的。Builder通常是它所构建的雷达静态成员类。
//Builder Pattern
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
public static class Builder { // Required parameters
private final int servingSize;
private final int servings;
// Optional parameters - initialized to default values
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
}
也可以用lombok的@Builder构造一个实例,属性不需要单独set。
Java return this
将方法的返回值类型指定为当前 Class ,那么,在方法体的最后可以直接 return this ,从而可以形成一个类似于 Builder Patern 的效果。但是依然会存在不一致性的问题。