본문 바로가기
Design Pattern

4. 빌더 패턴 (Builder Pattern)

by 킹차니 2021. 11. 18.

 

 

빌더 패턴

빌더 패턴은 동일한 프로세스를 거쳐 다양한 구성의 인스턴스를 만드는 방법이다.

복잡한 인스턴스를 만드는 프로세스를 독립적으로 분리할 수 있다.

 

 

만약 아래와 같이 TourPlan 객체를 만든다고 해보자.

TourPlan class는 아래와 같다.

 

TourPlan

tour의 이름, 몇박 몇일일지, 출발 날짜 등과 같은 필드가 보인다.

구체적인 plan인 DetailPlan class는 아래와 같다.

 

DetailPlan

 

이제 사용하는 코드는 아래와 같다.

위와 같이 shortPlan과 tourPlan 인스턴스를 만들어 보았다. 

그런데 만약 이렇게 다양하고 복잡한 객체를 만들 때 shortPlan과 같은 짧은 여행은 setDays, setNights를 할 필요가 없을 것이다.

이 외에도 많은 종류의 객체가 생성될 수 있는데, 이를 위해 다양한 생성자를 만든다면 entity 클래스가 지저분해지고, 사용하는 입장에서도 어떤 때에 어떤 생성자를 사용해야할지 몹시 헷갈릴 것이다. 

 

하여 빌더패턴을 적용하면 인스턴스를 생성하는 법을 단계별로 정할 수 있다.

 

 

먼저 빌더 인터페이스를 정의한다.

 

그리고 아래와 같이 빌더 인터페이스를 구현한 DefaultBuilder

마지막으로 getPlan()으로 TourPlan 인스턴스를 얻을 수 있다.

 

이제 이를 사용하는 코드를 보자.

위와 같이 긴 여행이든 당일치기 여행이든 상관없이 별도의 생성자를 만들지 않고, 필요한 필드만을 선택하여 인스턴스를 만들 수 있다.

 

 

또한 아래와 같이 디렉터를 사용하여 만들 수도 있다.

TourDirector는 아래와 같다.

 

 

빌더 패턴의 장점:

1. 만들기 복잡한 객체를 순차적으로 만들 수 있는 방법을 제공한다.

2. 위와 같이 만들면 클라이언트 코드는 빌더패턴대로 그대로 따라가면서 만들면 된다.

3. 복잡한 생성자를 간단하게 만들어준다. 

4. 디렉터를 사용한다면 복잡한 객체를 만드는 과정을 숨길 수 있다.

5. 다른 빌더를 만든다면, 동일한 프로세스를 거친다해도 다른 인스턴스를 만들 수 있다.(위의 예시로 VIPTourBuilder를 만들어서 필드를 추가할 수 있음)

6. 안정성을 보장할 수 있다.( 현재는 getPlan()에 별다른 코드가 없지만 getPlan()메서드에 별도의 로직을 넣어 값 검증을 할 수 있다.) 

 

빌더 패턴의 단점:

1. 클라이언트가 인스턴스를 만들기 위해 빌더 인스턴스를 만들어야 한다.(디렉터를 사용한다면 디렉터 인스턴스까지 만들어야한다.)

2. 인스턴스를 만드는 구조가 이전에 비해 복잡해진다.

 

 

 

 

자바, 스프링에서 빌더 패턴을 사용하는 예시:

 

자바의 StringBuilder또는 Stream에서 찾아볼 수 있다.

또한 Lombok을 사용하면 @Builder로 쉽게 빌더패턴을 적용할 수 있다.

 

스프링에서는 UriComponents가 builder패턴을 사용한다. (이 외에도 많음)

위의 UriComponents에 newInstance가 있는 것처럼 우리의 빌더에도 이를 적용해보면 아래와 같다.

newInstance를 사용하여 샤로운 인스턴스를 만드는것을 강제하는 것이다.

 

 

출처: 인프런 백기선님 '코딩으로 학습하는 GoF 강의'
https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4