[아이템2] 생성자에 매개변수가 많다면 빌더를 고려하라

2023. 4. 27. 13:44Effective Java

반응형

생성자와 정적팩터리의 공통적 제약: 선택적 매개변수가 많을 때 적절히 대응하기 어렵다.

매개변수가 많으면 코드를 읽을 때 각 값의 의미가 무엇인지 헷갈릴테고, 매변수가 몇개인지도 주의해서 세어보아야한다. 찾기 어려운 버그로 이어질 수도 있다.

대안1. 점층적 생성자 패턴

매개변수 개수만큼 생성자를 늘리는 방식

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

사용자가 설정하길 원치않는 매개변수까지 어쩔 수 없이 값을 지정해야한다. 매개변수 조합에 따라 생성자 수가 쓸데없이 많이 늘어날 수 있다. 불변 클래스가 아니기 때문에 오류가 생길 가능성이 크고, 안전성이 낮다.

대안2. 자바빈즈 패턴

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

NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServing(8);
cocaCola.setCalories(100);
cocaCola.setFat(0);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);

장점: 기존에 사용하던 점층적 생성자 방식에 비해서 가독성과 사용성이 증가되었다.

단점: 생성자에서 매개변수를 확인할 수 없기 때문에 객체가 완전히 완성되기 전까지는 일관성이 무너진 상태에 놓이게 된다.

대안3. 빌더패턴

필수 매개변수만으로 생성자를 호출해서 객체를 만든 후, 필요하면 빌더에서 제공하는 setter메소드로 선택 매개변수 값을 추가한다.

public class Person{
 ...(중략)...
 public static class Builder{
  //필수 매개변수
  private final String name;
  private final Integer age;
  //선택 매개변수
  private Integer birth = 000000;
  private boolean isStudent = true;
  //필수 매개변수만 받는 생성자 호출
  public Builder(String name, Integer age){
   this.name = name;
   this.age = age;
  }
  //선택 매개변수 setter
  public Builder birth(int val){
   birth = val;
   return this; 
  }
  public Builder isStudent(boolean val){
   isStudent = val;
   return this;
  }
  public Person build(){
   return new Person(this);
  }
 }
 private Person(Builder builder){
  name = builder.name;
  age = builder.age;
  birth = builder.birth;
  isStudent = builder.isStudent;
 }
}

호출 예시)

Person me = new Person.Builder("유나", 23)//필수 인자
 .isStudent(false).build(); //선택 인자

특징

1) 빌더의 setter는 자기 자신을 호출하기 때문에 메소드를 연속적으로 호출 가능하다.

2) 작성하기 쉽고 가독성과 사용성이 높아진다.

3) 유연하다.

반응형