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

ajufresh·2020년 2월 19일
0

Effective Java 3/E

목록 보기
2/9
post-thumbnail

블로그에 게시하는 위 글은 전체적인 내용 정리가 아닌
책을 읽으면서 새로 알게된 내용이나 제가 중요하다고 생각하는 내용을 정리한 글입니다.

백기선님의 유튜브와 책을 병행했다.

점층적 생성자 패턴

생성자, 정적 팩토리 메소드 둘 다 매개변수가 많을 때 처리가 어렵다.

예를 들어 식품 영양소 클래스에서 20개가 넘는 영양 정보들 (탄수화물, 지방, 총 칼로리 등 ...)이 들어가지만 정작 사용하는 변수들은 많지 않다.

그렇기 때문에 예전에는 받는 매개변수가 다른 생성자를 각각 만들어 객체를 생성해주었다.

public class Person {

    private String name;
    private Integer age;
    private Integer birth;
    
    public Person(String name, Integer age, Integer birth) {
    	this.name = name;
        this.age = age;
        this.birth = birth;
    }

    
    // 사용할 생성자 만들기
    public Person(String name, Integer age) {
    	this(name, age, 0);
    }
    
    public Person(String name) {
    	this(name, 0, 0);
    }


    ... (중략) ...

}

선택 매개변수가 많을 때

자바 빈즈 패턴(JavaBeans Pattern)

기본 생성자로 객체를 생성한 후에, Setter를 호출하여 값을 고정시키는 방법이다.

public class Person {

	private String name; // 필수
    private Integer age = 0;
    private Integer birth = 0;
    
    public Person() {} // 기본 생성자
    
    // setter
    public void setName(String name){
    	this.name = name;
    }

    ... (중략) ...

}

사용할 때에는 아래와 같이 사용한다.

Person me = new Person();

me.setName("fresh"); 
me.setAge(10); 
me.setBirth(100070);

장점

  1. 기존에 사용하던 점층적 생성자 방식에 비하여 가독성사용성이 증가되었다.

단점

  1. 하나의 객체를 만들기까지 여러번의 메소드를 호출한다.
  2. 객체가 완전히 완성되기 전까지는 일관성을 보장하지 않는다.
    -> 객체끼리 비교했을 때 오류가 날 수 있음

빌더 패턴(Builder Pattern)

클라이언트에서 필수 매개변수만 가지고 있는 생성자를 호출해서 객체를 만든 후,
필요하면 (빌더에서 제공하는) Setter메소드로 선택 매개변수의 값을 추가한다.

public class Person {

    private final String name;
    private final Integer age;
    private final Integer birth;
    private final boolean isStudent = true;

    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;
   }

}

빌더의 setter는 빌더 자기 자신을 호출하기 때문에 메소드를 연속적으로 호출 가능
-> 메소드 연쇄, 플루언트 API

사용할 때에는 아래와 같이 사용한다.

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

빌더 패턴은 계층적으로 설계된 클래스와 함께 쓰기 좋다.

장점

  1. 작성하기 쉽고 가독성과 사용성이 높아진다.
  2. 인자에 불변식 적용이 가능하다.
  3. 각 설정 메서드마다 가변인자 사용이 가능하다.
  4. 유연하다.

단점

  1. 빌더를 만드는 시간적인 비용이 발생한다.
profile
공블로그

0개의 댓글