Effective Java学习笔记之第2条 遇到多个构造器参数时考虑用构建器

时间:2022-08-27 23:17:33

第2条 遇到多个构造器参数时要考虑用构建器

  静态工厂和构造器有个共同的局限性: 它们都不能很好的扩展到大量的可选参数。

  JavaBeans 模式自身有着严重的缺点: 构造过程被分解到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。

  JavaBeans模式阻止了把类做成不可变得可能。

  Builder模式:不直接生产想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。然后客户端再builder对象上调用类似于setter方法,来设置每个相关的可选参数。最后,客户端调用无参的build方法来生产不可变对象。

  示例:

  // 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;

 

    public static class Builder {

      // Required parameters

      private final int servintSize;

      private final int servings;

      Optional parameters - initalized to default values

      private int calories = 0;

      private int fat = 0;

      private int carbohydrate = 0;

      private int sodium = 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 carbohydrate(int val) {

        carbohydrate = val;

        return this;

        }

      public Builder sodium(int val) {

        sodium = val;

        return this;

      }

      public NutritionFacts build() {

        return new NutritionFacts(this);

      }

    }  

    private NutritionFacts(Builder builder) {

      servingSize = bulder.servingSize;

      servings = bulder.servings;

      calories = bulder.calories;

      fat = bulder.fat;

      sodium = builder.sodium;

      carbohydrate = builder.carbohydrate;

    }

  }

 

  // 调用

  NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();

  builder 像个构造器一样,可以对其参数强加约束条件。

  

  // A builder for objects of type T

  public interface Builder<T> {

    public T builder();

  }

  

  Builder模式的确也有自身的不足:为了创建对象,必须先创建它的构建器。Builder模式还比重叠构造器模式更加冗长,因此它只在有很多参数时才能使用。

  简而言之:如果类的构造器或者静态工厂中具有多个参数,设计这种类时,builder模式就是不错的选择,特别是当大多数参数都是可选的时候。