해당 글은 Tstory 블로그 Dev inpa에 출처를 두고 있습니다.

이번 패턴은 Builder 패턴에 대해서 알아보도록 하자.

Builder?

먼저 늘 그랬듯이, 간단하게 패턴을 정의해보도록 하자.

객체의 생성에 있어, 매개변수의 선택권을 유연하게 하는 패턴!

위와 같이 간단하게 정의할 수 있을 것 같다.
말 그대로 객체의 생성을 매우 유연하게 해주는 패턴이다!
자세한 사항은 아래로 차근차근 알아보도록 하자.

사용 이유

예를 들어 학생 관리 프로그램을 위해 사용자 객체를 만든다고 생각해보자.
ID, 이름, 핸드폰 번호 등 필수적으로 들어가야 할 요소들이 있을 것이다.
하지만 객체의 필드에 만약 선택 사항이 포함되어 있다면?
해당 선택 사항을 매개변수로 입력 받아 객체를 생성해야 하는 상황이라면?

단순하게 아무 생각 없이 코드를 짜보면, 아래와 같을 것이다.

스크린샷 2024-01-17 오전 1 40 02

여러 방식의 입력을 받을 수 있는 생성자들을 구현했다.
하지만 이렇게 구현한 코드는 아름답고 깔끔하지 못하다.
필드에 선택 사항이 늘어날수록 생성자의 수도 점점 늘어나 점점 지저분해질 것이다.

따라서 아래의 방식들로 코드를 리팩토링 해보자!

Bean 패턴 (Setter)

Builder 패턴으로 넘어가기 이전에, Java Bean에 대해서 잠깐 알아보자.
이는 Setter와 관련된 개념으로, 매개변수의 주입에 초점을 둔다.

스크린샷 2024-01-17 오후 11 50 50

setter 메서드들을 필드 변수마다 만들어 주입을 해주는 것이다.
그러면 기본 생성자를 통해 객체를 생성한 뒤, 아래와 같이 주입할 수 있다.

스크린샷 2024-01-17 오후 11 52 13

하지만 setter를 엔티티에 public으로 열어놓는 것은 매우 위험하다.

Builder의 구현

따라서 최종적으로 Builder 패턴이 등장하게 되었다!
따로 Builder 클래스를 따로 구현하여, 해당 클래스가 객체를 생성하도록 한다.
Builder 클래스 내의 메서드들은 아래와 같이 구현된다.

스크린샷 2024-01-18 오전 12 16 15

각 메서드들의 반환 값을 Builder 클래스 본인으로 지정하게 되면 어떻게 되느냐?
아래의 사진과 같이 메서드 체이닝을 통해서 객체 생성이 쉽게 가능해진다.

스크린샷 2024-01-18 오전 12 22 36

이렇게 따로 매개 변수의 형식마다 생성자를 새로 만드는 것이 아닌,
또한 setter를 통해서 엔티티에 직접 접근하는 것이 아닌,
Builder라는 객체 생성 클래스를 거쳐서 간편하게 객체를 생성하도록 한다.

그 결과 선택 사항으로 넣은 멤버 변수만 초기화 되었음을 확인할 수 있다.
초기화시키지 않은 변수는 자동으로 null이 채워지게 된다.

스크린샷 2024-01-18 오전 12 23 05

장단점

빌더 패턴의 장점은 아래와 같다.

  • 필요한 매개변수의 이름이 메서드 이름과 동일하다.
    • 매개변수 주입 시에 헷갈리지 않아도 된다.
  • 빌더 클래스에 기본 값을 설정해버리면 디폴트 값을 따로 설정하지 않아도 된다.
  • 필수 멤버 변수와 선택 멤버 변수를 쉽게 구분할 수 있다.
    • 필수 멤버 변수는 Builder의 생성자로 받게끔 한다.
    • 선택 멤버 변수는 Builder의 메서드 만을 통해 선택하도록 한다.
  • 객체의 생성을 지연시킬 수 있다.
  • 초기화에 대한 검증을 멤버 변수 별로 분리할 수 있다.
  • 멤버에 대한 변경 가능성이 최소화 된다.

아래로는 빌더 패턴의 단점이다.

  • 빌더 패턴을 사용하면 클래스가 추가적으로 늘어나게 된다.
    • 이는 곧 코드의 복잡성을 증가시킨다.
  • 당연하게도 생성자 보다 성능은 떨어지게 된다.
    • 따라서 Static Factory Method와의 Trade-off를 잘 따져보아야 한다.

객체의 생성 지연

위에서 언급했던 Builder 패턴의 장점 중, 객체 생성 지연을 짚고 넘어가자.
Builder 클래스를 한 번 거쳐서 객체를 생성하는 특징이 있기 때문에,
객체의 생성을 유동적으로 지연시킬 수 있다.

아래와 같이 여러 명의 멤버를 동시에 가입시킨다고 가정해보면,
객체를 Builder 배열에 담아놓았다가 동시에 build 할 수 있다.

스크린샷 2024-01-18 오전 1 15 05

멤버 변수 검증

위에서 언급했던 Builder 패턴의 장점 중, 변수 검증을 짚고 넘어가자.
우리는 객체를 생성할 때, 매개변수를 검증해야 할 일이 반드시 있다.
예를 들어 회원가입을 진행할 때, 비밀번호의 형태를 검증할 수가 있을 것이다.
또는 이메일 인증을 받을 때 이메일의 형식을 검증할 수도 있을 것이다.

이 때 만약 아래와 같이 생성자에서 일일이 검증을 해야 한다면?
생성자가 여러개라면 생성자마다 예외 처리 코드를 구현해야 할 것이다.

스크린샷 2024-01-18 오전 12 32 50

하지만 Builder 패턴을 통해서 검증 절차를 간소화 할 수 있다!
객체를 생성하기 이전, Builder 객체에서 이를 검증하는 것이다.

스크린샷 2024-01-18 오전 12 34 02