首页 > 代码库 > 第二条 遇到多个构造器参数时,要考虑用构建器

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

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

如:

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

    public NutritionFacts(int servingSize, int servings, int calories,   int fat ){
           this(servingsSize, servings, calories, fat, 0);
    }
   
    public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium){
            this(servingsSize, servings, calories, 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 = caloriers;
            this.fat = fat;
            this.sodium = sodium;
            this.carbohydrate = carbohydrate;
    }

}

我们可以看到利用构造器方式,有多个参数时,很难控制其灵活性。因而我们选择尝试给每个值设置默认值:

public class NutritionFacts{
  private int servingSize = -1;
  private int servings = -1;
  private int calories = 0;
  private int fat = 0;
  private int sodium = 0;
  private int carbohydrate = 0;

  public NutritionFacts(){
     //   setters
     public void setServingSize(int val){
         servingSize = val;
    } 
    
     public void setServings(int val){
          servings = val;
     }
     //....
  }
}

 

  调用初始化

NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);

这是常见的javaBean模式,通过setter方法来构建对象,但是这也阻止了类做成不可变的可能,会有多线程安全问题。

 

那么我们来看看另外一种方式:

public class NutritionFacts{

   private final int servingSize;
   private final int srvings;
   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 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 carbohydrate(int val){ carbohydrate = val; return this; } public Builder sodium(int val){ sodium = val; return this; }
    // 在内部类中返回外部类对象的接口
public NutritionFacts build(){ return new NutritionsFacts(this); } } private NutritionFacts(Builder builder){ servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbodhydrate = builder.carbodhydrate; } }

 

调用方式:

NutritionFacts fact =  new NutritionFacts.builder(240,8).calories(100).sodium(46).carbohydrate(27).build();

这样通过builder模式,实现了可选参数构建对象实例。