effective解读-第二条 多构造参数时候使用构建器
-
构造参数不具名
-
参数多的话需要多个构造重载或者使用多个setter方法赋值
-
JavaBean在多线程调用的时候会有线程安全问题。如一个线程还没set完值得时候,另一个线程已经使用了。
1.普通模式
public class Demo {
private String filed1;
private String filed2;
private String filed3;
private String filed4;
private String filed5;
public static class DemoBuilder {
private final String filed1;
private final String filed2;
private final String filed3;
private final String filed4;
private final String filed5;
public DemoBuilder field1(String filed1) {
this.filed1 = filed1;
return this;
}
public DemoBuilder field2(String filed2) {
this.filed2 = filed2;
return this;
}
public DemoBuilder field3(String filed3) {
this.filed3 = filed3;
return this;
}
public DemoBuilder field4(String filed4) {
this.filed4 = filed4;
return this;
}
public DemoBuilder field5(String filed5) {
this.filed5 = filed5;
return this;
}
public Demo build(){
return new Demo(this);
}
}
private Demo(DemoBuilder builder){
this.filed1 = builder.filed1;
this.filed2 = builder.filed2;
this.filed3 = builder.filed3;
this.filed4 = builder.filed4;
this.filed5 = builder.filed5;
}
}
注意:
-
书中构建器使用了内部类,我们也可以直接使用外部类来创建(构造权限为protected)
-
多个参数是多少,书中给出4个或者更多的时候
-
Builder模式也有自身的不足,为了创建对象先创建构建器。
2.类层次中
package infosecuritydemo.demo;
import java.util.EnumSet;
import java.util.Set;
/**
* @author Programmer_Liu.
* @since 2021/3/24 18:12
*/
//上层抽象类
public abstract class Person {
/**
* 内部枚举,类型
*/
public enum Type{BLACK,YELLOW,WHITE}
/**
* 集合类属性,表明当前Person的类型
*/
final Set<Type> types;
/**
* 通过Builder初始化外部类属性
* 外部类是final类型,内部类的types是非final的(因为需要添加元素来最终初始化外部)
* 所以这里使用了clone()保证对象的不可变,否则builder中再次进行build值时候会导致
* 对象发生变化导致异常
*/
Person(Builder<?> builder) {
types = builder.types.clone();
}
/**
* 抽象Builder
* @param <T> 抽象类的Builder,子类Builder需要继承该Builder所以添加了递归类型参数
*/
abstract static class Builder<T extends Builder<T>>{
/**
* 设置Type类型的空集合用来映射外部类的types属性
*/
EnumSet<Type> types = EnumSet.noneOf(Type.class);
/**
* 链式编程方式初始化Builder映射外部类的属性
*/
public T addType(Type type){
types.add(type);
return self();
}
abstract Person build();
/**
*递归类型参数,通过该方法可以获取子类自己的Builder
*/
protected abstract T self();
}
}
//下层类实现类1