【Effective Javaを読む】　第２章　項目２　『数多くのコンストラクタパラメータに直面した時にはビルダーを検討する』

#数多くのコンストラクタパラメータに直面した時にはビルダーを検討する

newする時にパラメータをたくさん渡してあげなきゃいけないようなクラスを作る時は
「ビルダー」を使うと可読性も安全性もあって良いよって話

##サンプルコード

NutritionFactsという栄養成分を表すクラスが
一人前の分量、容器当たりの量、一人前のカロリー、etc　たくさんのフィールドを持っている場合を例にして3つのパターンで考えてみる
・テレスコーピングコンストラクタ・パターン
　パラメータが多くなるとnewする時に引数に何を渡せば良いかわかりづらくなるし、可読性も下がってしまうのがデメリット

・JavaBeansパターン
　テレスコーピングコンストラクタ・パターンと違い可読性は上がるが、パラメータを設定している途中で不整合な状態ができてしまう

・ビルダーパターン
　テレスコーピングコンストラクタとJavaBeansのいいとこ取り！


```java:例１
//テレスコーピングコンストラクタ・パターン
public class NutritionFacts{
    private final int servingSize;  //(mL)      　必須
    private final int servings;     //(容器当たり)  必須
    private final int calories;     //          　オプション
    private final int fat;          //(g)       　オプション
    private final int sodium;       //(mg)      　オプション
    private final int carbohydrate; //(g)       　オプション

    public NutritionFacts(int servingSize, int servings){
        this(servingSize, servings, 0, 0, 0, 0);
    }

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

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

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

//newする時　見辛いね
NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);

```



```java:例２
//JavaBeansパターン
public class NutritionFacts{
    private int servingSize  = -1; //(mL)      　必須
    private int servings     = -1; //(容器当たり)  必須
    private int calories     = 0;  //          　
    private int fat          = 0;  //(g)       　
    private int sodium       = 0;  //(mg)      　
    private int carbohydrate = 0;  //(g)       　

    public NutritionFacts(){ }

    //セッター
    public void setServingSize(int val)  { servingSize = val;}
    public void setServings(int val)     { servings = val;}
    public void setCalories(int val)     { calories = val;}
    public void setFat(int val)          { fat = val;}
    public void setSodium(int val)       { sodium = val;}
    public void setCarbohydrate(int val) { carbohydrate = val;}
}

//newする時　見易いけどsetしてる途中にアクセスされたらちょっと困る
NutritionFact cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);

```

```java:例３
//ビルダーパターン
public class NutritionFacts{
    private final int servingSize;  //(mL)      　
    private final int servings;     //(容器当たり)
    private final int calories;     //          　
    private final int fat;          //(g)       　
    private final int sodium;       //(mg)      　
    private final int carbohydrate; //(g)       　

    public static class Builder{
        //必須パラメータ
        private final int servingSize;  //(mL)      　
        private final int servings;     //(容器当たり)
        
        //オプションパラメータ
        private int calories     = 0;  //          　
        private int fat          = 0;  //(g)       　
        private int sodium       = 0;  //(mg)      　
        private int carbohydrate = 0;  //(g)   

        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 sodium(int val){
            sodium = val;
            return this;
       }

       public Builder carbohydrate(int val){
            carbohydrate = val;
            return this;
       }

       public NutritionFacts build() {
           return new NutritionFacts(this);
       }
    }

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

//newする時　見易いし安全！
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
    calories(100).sodium(35).carbohydrate(27).build();

```

#続く
【Effective Javaを読む】　第２章　項目３　『privateのコンストラクタかenum型でシングルトン特性を強制する』
https://qiita.com/Natsukii/items/ccd6893ce8add04d1777