Builder 패턴
책/Effective Java

Builder 패턴

728x90
반응형
정적 팩토리 메서드 , 생성자  
- 매개변수가 많을 때, 선택적으로 고려해야한다면 불편함 존재 
  • 기존 해결 방법 : 

점층적 생성자 패턴(Telescoping Constructor Pattern) 

필수적인 파라미터들에 대한 생성자 설정 후, 선택적인 파라미터에 대해서는 해당 파라미터를 포함한 생성자를 연쇄적 호출
이를 통해 모든 파라미터들이 설정된 객체가 만들어진다. 

장점 : 

      파라미터들이 유효한지를 생성자를 통해서 확인하면 일관성 유지 보장 

문제점 :

  1. 클라이언트가 원하지 않는 파라미터까지 설정해야 한다. 
  2. 개발자의 입장에서도 Class의 라인 수 증가, 호출 수 증가 - 클라이언트 코드를 작성하거나 읽기 어려운 문제 발생 

자바빈즈 패턴(JavaBeans Pattern)

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

장점 : 점층적 생성자 패턴의 단점들 보안 → 코드가 길어지지만, 인스턴스 생성이 쉽고, 이를 통한 가독성이 좋은 코드 

단점 : 

  • 객체 생성을 위해 메서드 여러개 호출 필요
  • 객체 생성 이전까지는 일관성(Consistency)가 깨진 상태 
    • 불변 클래스로 만들기 불가 
    • 스레드 안전성(Thread-safe)를 위해서는 추가 작업 필요 
일관성이 깨진다 
= 디버깅이 어려운 문제 발생(런타임 에러로 인해 버그의 위치 쉽게 파악하기 힘듦) 
불변성 (immutablility)
- 어떠한 변경도 허용하지 않는다. 
ex) String 객체 
불변식 (invariant)
프로그램이 실행되는 동안 반드시 만족해야하는 조건 
- 변경은 할 수 있으나, 주어진 조건 내에서만 허용한다. 
ex) List의 크기 >= 0 , Period.start < Period.end 

 

해결방법

  • Freezing

해당 객체를 사용 불가로 만듦(얼린다) -  unfreezing 이후에 객체 사용 가능

하지만 해당 방법 난이도 hard → 실전에서 사용 X 

 


Builder 패턴 

클라이언트는 필요한 객체를 직접 만든다. 
필수 매개변수만으로 생성자를 호출하여 빌더 객체를 Get 이후, 빌더 객체를 통해 setter 를 사용하여 선택적 매개변수 설정 
마무리로 build 메서드 호출로 객체 생성 완료

 

final을 통해 UserOfBuilder 클래스를 불변으로 설정

빌더의 setter 는 빌더 자신을 반환하기 때문에(return this;) 연쇄적 호출 가능 → 메서드 체이닝

 

메서드 체이닝 설명 예시

이처럼 클라이언트에서 해당 클래스를 사용할 때 코드도 쓰기 쉽고, 읽기도 편하다 

cf) 불변식 보장을 위한 방법
잘못된 매개변수를 발견하기 위해서는 불변식을 검사해야하는데 
빌더로부터 매개변수를 복사 후, 해당 객체 필드들도 검사한다. 
이를 통해 안전성을 보장할 수 있다. 

Builder 패턴 사용 예시 

빌더 패턴은 계층적으로 설계된 클래스와 함께 쓰기 좋다
각 계층 클래스 별로 관련 빌더 정의
- abstract Class & abstract Builder / Construct Class & Construct Bulider
  • 이 때 추상 메서드인 self를 통해 하위 클래스에서는 형변환하지 않아도 메서드 연쇄 지원 가능 
    • 추상 빌더에서 self에서 this를 리턴하기 때문에
    • 공반환 타이핑 - 하위 클래스 메서드에서 상위 클래스 메서드가 정의한 return 타입이 아닌, 그 하위 타입을 반환하는 기능 
  • 추상 클래스를 상속받은 하위 클래스들은 본인들에 맞는 파라미터를 받는 setter를 빌더를 통해서 적용 
ex) Pizza는 코드보면서 설명 

 

Builder 패턴 장점 정리 

  • 점층적 생성자 패턴보다 코드의 간결성 / 자바빈즈 패턴에 비해 안전성 보장 
  • 각각 만들어놓은 setter를 통해 매개변수를 여러 개를 유연성있게 처리가 가능하다. 
  • 이러한 처리로 인해 메서드를 여러 번 호출한 후 한번에 넘겨지는 매개변수들을 통해 하나의 필드로 모을 수 있음
  • 유지보수 혹은 서비스 고도화에서는 API 상으로 매개변수가 늘어나는 경우가 많아 Builder 패턴으로 시작하는 것이 효율적

Builder 패턴 고려해야할 점

  • 객체를 만들기 위해서는 Builder를 만들어주어야함 
  • 성능에 민감한 상황에서는 문제가 될 수 있음 

추가적 코멘트

Spring에서는 Builder 어노테이션을 제공하고 있기 때문에 추가적인 설정이 필요하지 않다면 쉽게 생성 가능 

 

728x90
반응형