#数多くのコンストラクタパラメータに直面した時にはビルダーを検討する
newする時にパラメータをたくさん渡してあげなきゃいけないようなクラスを作る時は
「ビルダー」を使うと可読性も安全性もあって良いよって話
##サンプルコード
NutritionFactsという栄養成分を表すクラスが
一人前の分量、容器当たりの量、一人前のカロリー、etc たくさんのフィールドを持っている場合を例にして3つのパターンで考えてみる
・テレスコーピングコンストラクタ・パターン
パラメータが多くなるとnewする時に引数に何を渡せば良いかわかりづらくなるし、可読性も下がってしまうのがデメリット
・JavaBeansパターン
テレスコーピングコンストラクタ・パターンと違い可読性は上がるが、パラメータを設定している途中で不整合な状態ができてしまう
・ビルダーパターン
テレスコーピングコンストラクタとJavaBeansのいいとこ取り!
例1
//テレスコーピングコンストラクタ・パターン
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);
例2
//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);
例3
//ビルダーパターン
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を読む】 第2章 項目3 『privateのコンストラクタかenum型でシングルトン特性を強制する』
https://qiita.com/Natsukii/items/ccd6893ce8add04d1777