본문 바로가기
Java & Kotlin/Effective Java

[Effective Java 3/E] Item 2. 빌더 패턴

by kiwi_wiki 2021. 1. 5.

점층적 생성자 패턴 (telescoping constuctor pattern)

 필수 매개변수만 받는 생성자, 필수 매개변수와 선택 매개변수 n 개를 받는 생성자의 형태로 생성자를 늘려가는 방식

public class NutritionFacts{
	private final int servingSize;
    private final int servings;
	private final int colories;
	private final int fat;
	private final int sodium;
    private final int carbonydrate;
    
    public NutritionFacts (int servingSize, int servings){
    	this(servingSize, servings, 0);
    }
  
    public NutritionFacts (int servingSize, int servings, int calories){
    	this(servintSize, servings, calories, 0);
    }
    
    public NutritionFacts (int servingSize, int servings, int calories, int fat){
    	this(servintSize, servings, calories, fat, 0);
    }

}


NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0);

매개변수가 많아지면 클라이언트 코드를 작성하거나 읽는 것이 어려워진다

 

자바 빈즈 패턴 (JavaBeans pattern)

 매개변수가 없는 생성자로 객체를 만든 후, 세터 메서들을 호출해 원하는 매개변수의 값을 설정하는 방식

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() {}
    
    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; }
    
}


NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);

객체 하나를 만들려면 매서드를 여러 개 호출해야 하고, 객체가 완전히 생성되기 전까지 일관성이 무너진 상태이다

 클래스를 불변으로 만들 수 없다

 

빌더 패턴 (Builder pattern)

 명명된 선택적 매개변수를 흉내 낸 것

 계층적으로 설계된 클래스와 함께 쓰기 좋다

 빌더 하나로 여러 객체를 순회하면서 만들 수 있고, 빌더에 넘기는 매개변수에 따라 다른 객체를 만들 수도 있다

public class NutritionFacts {
	private final int servingSize;
    private final int servings;
    private final int calories;
    
    public static class Builder {
    	private final int servingSize;
    	private final int servings;
        
        private int calories = 0;
        
        public Builder(int servingSize, int servings){
        	this.servingSize = servingSize;
            this.servings = servings;
        } 
        
        public Builder calories(int val) { calories = val; return this }
    }
    
    private NutritionFacts(Builder builder) {
    	servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
    }
    
}


NutritionFacts cocaCola = new NutritionFacts().Builder(240,8).calories(100).build();

 객체를 만들려면 빌더를 만들어야 함. 빌더 생성 비용이 크지 않지만 성능에 민감한 상황에서는 문제가 될 수 있다

 

매개변수 중 다수가 필수가 아니거나 다른 타입이라면 빌더 패턴을 사용하는 게 다른 패턴에 비해 낫다.

728x90
반응형