欢迎来到刘志红的博客

别人说程序员是“搬砖”的码农,但我们知道自己是追求个性的艺术家。也许我们不会过多的在意自己的外表和穿着,但在不羁的外表下,骨子里追求着代码的美、系统的美、设计的美。
扩大
缩小

effective解读-第二条 多构造参数时候使用构建器

多参数构造器缺点:

  1. 构造参数不具名

  2. 参数多的话需要多个构造重载或者使用多个setter方法赋值

  3. 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;
  }
}

注意:

  1. 书中构建器使用了内部类,我们也可以直接使用外部类来创建(构造权限为protected)

  2. 多个参数是多少,书中给出4个或者更多的时候

  3. 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
@ToString
public class EuropePerson extends Person {
   /**
    * 内部枚举类
    */
   public enum Size {BIG, STRONGER}

   /**
    * 独有属性,体型
    */
   private final Size size;

   private EuropePerson(Builder builder) {
       //初始化继承属性
       super(builder);
       //初始化继承属性独有属性
       this.size = builder.size;
  }

   public static class Builder extends Person.Builder<Builder> {
       /**
        * 外部类映射属性
        */
       private final Size size;

       /**
        * 直接通过构建器对象初始化属性
        */
       public Builder(Size size) {
           this.size = Objects.requireNonNull(size);
      }

       //通过构建器创建外部类对象
       @Override
       EuropePerson build() {
           return new EuropePerson(this);
      }

       @Override
       protected Builder self() {
           return this;
      }
  }
}
//下层实现类2
@ToString
public class OtherPerson extends Person {

   /**
    * 独有属性
    */
   private final boolean otherField;

   /**
    * 通过构建器初始化当前类
    */
   OtherPerson(Builder builder) {
       super(builder);
       otherField = builder.otherField;
  }

   public static class Builder extends Person.Builder<Builder> {
       /**
        * 外部类字段的映射
        */
       private boolean otherField;

       /**
        * 通过链式编程的方式初始化属性
        *
        * @param otherField
        * @return
        */
       public Builder otherField(boolean otherField) {
           this.otherField = otherField;
           return this;
      }

       /**
        * 构建外部类对象
        *
        * @return
        */
       @Override
       OtherPerson build() {
           return new OtherPerson(this);
      }

       @Override
       protected Builder self() {
           return this;
      }
  }
}

构建对象

public class Demo {
   public static void main(String[] args) {
       EuropePerson europePerson = new EuropePerson.Builder(EuropePerson.Size.BIG)
              .addType(Person.Type.BLACK)
              .addType(Person.Type.WHITE)
              .build();

       OtherPerson otherPerson = new OtherPerson.Builder()
              .addType(Person.Type.BLACK)
              .addType(Person.Type.WHITE)
              .otherField(true).build();
  }
}

 

posted on 2021-03-25 14:23  MR_程序猿刘  阅读(33)  评论(0编辑  收藏  举报

导航