-
아이템2. 생성자에 매개변수가 많다면 빌더를 고려하라책/이펙티브자바 2021. 6. 20. 13:53
정적팩토리나 생성자에는 똑같은 제약이 있다.
→ 둘 다 선택적 매개변수가 많을때 적절히 대응이 어렵다는 점
이렇게 선택적 매개변수가 많을때는 어떻게 효율적으로 사용할 수 있을까 ?
- 점층적 생성자 패턴
- 자바빈즈 패턴
- 빌더 패턴
점층적 생성자 패턴 (telescoping constructor pattern)
필수 매개변수만 받는 생성자 → 필수 매개변수, 선택 매개변수1 ... 필수 매개변수, 선택 매개변수 n ... 이렇게 전부 다 받는 생성자까지 늘려가는 방식
→ 쓸 수는 있지만, 매개변수 개수가 많아지면 클라이언트 코드 작성이나 읽기가 어렵다.
→ 각 값의 의미가 헷갈림.
→ 타입이 같은 매개변수가 연달아 있으면 찾기 어려움.
→ 결국 런타임에 엉뚱한 동작 발생.
자바빈즈 패턴 (JavaBeans pattern)
매개변수가 없는 생성자로 객체를 만든 후, setter 메서드를 호출해 원하는 매개변수의 값을 설정하는 방식
→ 코드가 길어지지만 인스턴스 생성이 쉬움.
→ 코드 가독성이 좋음.
→ 객체 하나를 만들기 위해선 setter 메소드 호출이 너무 잦을 수 있음.
→ 객체가 완전히 생성되기 까지는 일관성 (consistency)가 무너진 상태임.
→ 클래스를 불변으로 만들수 없음.
→ 스레드 안전성을 위해서는 추가작업이 필요함.
빌더 패턴 (Builder pattern)
점층적 생성자 패턴의 안전성 + 자바빈즈 패턴의 가독성 ⇒ 빌더 패턴
클라이언트는 필요한 객체를 직접 만드는 대신, 필수 매개변수만으로 생성자(혹은 정적 팩토리)를 호출해 빌더 객체를 얻는다.
→ 쓰기 쉽고, 읽기 쉬움.
→ 유연하다. (빌더 하나로 여러 객체를 순회하면서 만들 수 있고, 빌더에 넘기는 매개변수에 따라 다른 객체를 만들 수 도 있다.)
→ 코드가 장황해 매개변수가 4개 이상은 되어야 값어치를 한다. (API 는 시간이 지날수록 매개변수가 많아지는 경향이 있다.)
→ 객체를 만들기 이전에 빌더 부터 만들어야 한다. (빌더 생성 비용이 크지는 않지만 성능에 민감한 상황에서는 문제가 될 수 있음.)
→ 생성자나 정적팩토리 방식으로 시작했다가 추후에 매개변수가 많아지면 빌더 패턴으로 바꿀수도 있지만, 애초에 빌더로 시작하는 편이 권장된다.
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 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); } } public 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(35) .carbohydrate(27) .build();
'책 > 이펙티브자바' 카테고리의 다른 글
아이템4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) 2021.06.20 아이템3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) 2021.06.20 아이템1. 생성자 대신 정적 팩토리 메소드를 고려하라 (0) 2021.06.20 어떻게 읽을지 ... (0) 2021.06.20 이펙티브자바 책 샀다. (0) 2021.06.18