[Effective JAVA] Item2. 생성자에 매개변수가 많다면 빌더를 고려하라

보람찬하루·2024년 4월 20일
0

Effective JAVA

목록 보기
2/8

배경

선택적 매개변수가 많을 때 적절하게 대응하기 어렵다
</br>

선행적 해결 방법

  1. 점층적 생성자 패턴
    : 필수 매개변수만 받는 생성자 ..>..>필수 매개변수 + 선택 매개변수 전체를 받는 생성자

    public class NutritionFacts {
    	private final int servingSize; // (ml, 1회 제공량) 필수
    	private final int servings; // (회, 총 n회 제공량) 필수
    	private final int calories; // (1회 제공량당) 선택
    	private final int fat; // (g/1회 제공량) 선택
    	private final int sodium; // (mg/1회 제공량) 선택
    	private final int carbohydrate; // (g/1회 제공량) 선택
        
    	public NutritionFactsint servingSize, int servings) {
    		this(servingSize, servings, 0;
    	public NutritionFactsint servingSize, int servings, int calories) {
    		this(servingSize, servings, calories, 0;
    	}
    	public NutritionFacts(int servingSize, int servings,int calories,
    	int fat) {
    		this(servingSize, servings, calories, fat, 0);
    		}
    	public NutritionFacts(int servingSize, int servings, int calories,
    	, int fat, int sodium) {
    		this(servingSize, servings, calories, fat, sodium, 0);
    		}
    	public NutritionFactsdnt 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; 
    	}
    }

    • 단점
      1. 설정을 원하지 않는 매개변수까지 포함해야하고 어쩔 수 없이 그런 매개변수에도 값을 지정해줘야 한다.
      2. 매개변수가 많아지면 클라이언트 코드를 작성하거나 읽기 어렵고 에러 발생 위험이 높다.

      💡 확장이 어렵다

  2. Java Beans Pattern

    : 매개변수가 없는 생성자로 객체 생성 후 setter를 통해 매개변수 값 설정

    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 NutritionFactsO { }
    	// 세터 메서드들
    
    	public void setServingSize(int val) { servingSize = val; }
    	public void setServings(int val) { servings = val; }
    	public void setCaloriesdnt(int val) { calories = val; }
    	public void setFatdnt(int val) { fat = val; }
    	public void setSodium(int val) { sodium = val; }
    	public void setCarbohydrate(int val) { carbohydrate = val; }	
    }
    • 단점
      1. 객체 하나를 만들기 위해 메서드를 여러개 호출해야 함
      2. 객체가 완전히 생성되기 전까지 일관성이 무너진 상태

      💡 일관성이 깨지고 불변으로 만들 수 없다.

Builder Pattern

: 필수 매개변수로 생성자를 호출해 빌더 객체를 얻음

클래스 안에 정적 멤버 클래스로 생성

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);
}
	private NutritionFacts(Builder builder) {
		servingSize = builder.servingSize;
		servings = builder.servings;
		calories = builder.calories;
		fat = builder.fat;
		sodium = builder.sodium;
		carbohydrate = builder.carbohydrate;
		}
  • 장점
    1. 빌더의 setter 메서드들은 빌더 자신을 반환하기 때문에 연쇄적으로 호출할 수 있다.
      이런 방식을 메서드 호출이 흐르듯 연결된다.
    2. 계층적으로 설계된 클래스와 함께 쓰기에 좋다
  • 단점
    1. 객체 생성 전 빌더를 먼저 만들어야한다
    2. 매개변수가 4개 이상은 되어야 값어치가 있다.

☀️ 핵심정리
생성자나 정적 팩터리가 처리해야하 할 매개변수가 많다면 빌더 패턴을 선택하는게 더 낫다. 매개변수 중 다수가 필수가 아니거나 같은 타입이면 특히 더 그렇다. 빌더는 점층적 생성자보다 클라이언트 코드를 읽고 쓰기가 훨씬 간결하고 자바빈즈보다 훨씬 안전하다.

profile
를 만들어 가자

2개의 댓글

comment-user-thumbnail
2024년 4월 20일

덕분에 이펙티브 자바를 공부하네요 ... 넘조아요

답글 달기
comment-user-thumbnail
2024년 4월 21일

와 정적 팩토리 메서드랑 빌더 패턴 각각을 어느 상황에 쓰면 좋을지 항상 궁금했는데 이번에 확실히 알아갑니다아!!!!!!!!

답글 달기