Java 构建器

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

考虑用一个类表示包装食品外面显示的营养成分标签。这些标签中有几个域是必须的:每分的含量,每罐的含量以及每份的卡路里,还有超过20个可选域。对于这样一个类,应该选用那种构造器或者静态方法来编写呢?我们一向习惯采取重叠构造器模式。

    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 NutritionFacts(int servingSize,int servings){
        this(servingSize,servings,0);
      }

        public NutritionFacts(int servingSize,int servings,int calories){
        this(servingSize,servings,calores,0);
      }
      
       public NutritionFacts(int servingSize,int servings,int calories,int fat,int sodium){
        this(servingSize,servings,calores,fat,sodium,0);
      }

       public NutritionFacts(int servingSize,int servings,int calories,int fat,int sodium,int carbohydrate){
         this.servingSize=servingSize;
         this.servings=servings;
         this.calories=calories;
         this.fat=fat;
         this.sodium=sodium;
         this.carbohydrate=carbohydrate;
      }
    }

这种构造器通常需要许多你不想设置的参数,但是还不得不为他们传递值。在这个例子中,我们就给fat传递了0。如果仅仅6个参数,看起来还不算太糟,问题是随着参数的增加,他们很快就失去了控制。

遇到许多构造起参数的时候,还有第二种替代的办法,即javaBeans模式,在这个模式下,调用一个无参构造器来创造对象,然后调用setter方法来设置每个必须的参数,以及每个相关的可选参数:

    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 NutritionFacts(){}
      
      //Setters
      public void setServingSize(int val){servingSize=val;}
      //........就不多写了
    }

遗憾的是,JavaBeans模式自身有着很严重的缺点。因为构造过程被分到几个调用中,在构造过程中JavaBean可能处于非一致的状态。JavaBeans模式阻止了把类做成不可变的可能,这就需要程序员付出额外的努力来确保他的线程安全。

幸运的是,还有第三种代替方法,既能保证像重叠构造器模式那样的安全性,也能保证像JavaBeans模式那么好的可读性。这就是Builder模式的一种形式。不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的build方法来生成不可变的对象。

    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{
        private final int servingSize;//必要
        private final int servings;//必要
        private final int calories=0;//可选
        private final int fat=0;//可选
        private final int sodium=0;//可选
        private final 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 NutritionFacts build(){
          return new NutritionFacts(this);
        }
      }

       private NutritionFacts(Builder builder){
         this.servingSize=builder.servingSize;
         this.servings=builder.servings;
         this.calories=builder.calories;
         this.fat=builder.fat;
         this.sodium=builder.sodium;
         this.carbohydrate=builder.carbohydrate;
      }
    }

构造的函数

NutritionFacts cacaCola=new NutritionFacts.Builder(240,9).calories(100).sodium(23).build();

你可能感兴趣的:(Java 构建器)