책 내용 요약/Effective Java 3판
[ITEM2] 생성자에 매개변수가 많다면 빌더를 고려하라.
DEV_SJ
2020. 2. 25. 15:15
생성자에 매개변수가 많다면 빌더를 고려하라.
정적 팩터리 메서드나 생성자는 매개변수가 많을 때 적절히 대응하기 어렵다.
일반적으로 사용하는 다음의 2가지 경우를 보자.
기존 패턴
1.점층적 생성자 패턴 - 필수 생성자, 선택 매개변수 1개를 받는 생성자, 선택 매개변수 2개를 받는 생성자, ..., n개를 받는 생성자
단점: 매개변수가 많아지면 클라이언트가 코드를 작성하기 어렵고 읽기도 어렵다.
2.자바빈즈 패턴 - 매개변수가 없는 생성자로 객체를 만든 후 세터를 이용해서 결정하는 방식
단점: 객체가 완성되기 전까지 일관성이 무너진 상태에 놓이게 된다.
빌더 패턴
클라이언트는 필수 생성자를 호출해 빌더 객체를 얻고 빌더 객체의 세터메소드를 사용하여 원하는 선택 매개변수를 설정한다.
객체 선언
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 int calories=0;
private int fat=0;
private int sodium=0;
private 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 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;
}
}
클라이언트 코드
NutritionFacts cocaCola = new NutritionFacts.Builder(240,8)
.calories(100).sodium(20).carbohydrate(27).build();
다음과 같이 빌더패턴을 사용한다면 클라이언트가 코드및 읽기가 쉬워진다.
빌더 패턴에 장점만 있는 것은 아니다. 객체를 만드려면 이전에 빌더 객체를 먼저 만들어야한다.
빌더 객체의 생성비용이 크지는 않지만 성능에 민감하다면 문제가 될 수 있다.
또한 코드가 장황해져서 매개변수가 4개이상은 되야 값어치를 한다.
정리
생성자나 정적팩터리가 처리해야할 매개변수가 많다면 빌더패턴을 선택하는게 낫다.