정적 팩터리와 생성자에는 공통 제약인 하나 있는데, “선택적 매개변수가 많을 때 적절히 대응하기 어렵다” 는 점이다.
이럴 때마다 프로그래머들은 점층적 생성자 패턴을 즐겨 사용했다.
필수 매개변수와 선택 매개변수를 위한 생성자 … 형태로 늘려가는 방식이다.
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, calories, 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;
}
}
이 클래스의 인스턴스를 만들려면 원하는 매개변수를 모두 포함한 생성자를 호출하면 된다.
NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);
만약 매개변수가 늘어난다면? 이는 금세 걷잡을 수 없게 된다!
→ 정리하면, 점층적 생성자 패턴은 매개변수 개수가 많아지면 클라이언트 코드를 작성하거나 읽기 어렵다!
두번째 대안은 JavaBeans 패턴이 있다.
매개변수가 없는 생성자로 객체를 만든 후, setter 메서드들을 호출해 원하는 매개변수 값을 설정하는 방식이다.
public class NutritionFacts2 {
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 NutritionFacts2() {
}
public void setServingSize(int servingSize) {
this.servingSize = servingSize;
}
public void setServings(int servings) {
this.servings = servings;
}
public void setCalories(int calories) {
this.calories = calories;
}
...
}
→ 코드가 길어지긴 했지만 인스턴스를 만들기 쉽고, 그 결과 더 읽기 쉬운 코드가 되었다.
NutritionFacts2 cocaCola = new NutritionFacts2();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
...
하지만 불행히도 심각한 단점을 지니고 있다. 이 패턴은 객체 하나를 만들려면 메서드를 여러 개 호출해야 하고, 객체가 완전히 생성되기 전까지는 일관성이 무너진 상태에 놓이게 된다.