본문 바로가기

Develop/DESIGN PATTERNS

[GoF Design Pattern] 빌더 패턴 (Builder pattern)

1. 빌더 패턴이란?

인스턴스를 만들 때, 해당 인스턴스는 다양한 구성으로 만들어질 수 있다.

이렇게 다양한 구성으로 만들어지는 인스턴스를 동일한 프로세스를 통해 만들 수 있게끔 도와주는 패턴이다.

 

만약 빌더 패턴을 사용하지 않는다면

다양한 파라미터를 지원하는 생성자를 만들고 싶을 때 코드가 장황해질 수 있다. 따라서 클라이언트가 어떤 생성자를 사용할 지 애매해진다.

또한 필드값에 대한 유효성 검사가 불가능하다. 따라서 불완전한 인스턴스를 생성할 가능성이 있다.

그리고 생성자에서 몇몇 파라미터만 사용하는 경우라면 수많은 기본값이나 null값을 입력해야 한다.

 

따라서 이러한 문제들을 빌더 패턴을 통해서 해결할 수가 있다.

2. 구현 방법

다음과 같은 구조를 가져갈 수 있다.

 

이때 특정 프로세스들이 반복된다면 미리 만들어진 셋을 Director 클래스에 넣어두고 사용할 수도 있다!

public class TourDirector {

    private TourPlanBuilder tourPlanBuilder;

    public TourDirector(TourPlanBuilder tourPlanBuilder) {
        this.tourPlanBuilder = tourPlanBuilder;
    }

    public TourPlan cancunTrip() {
        return tourPlanBuilder.title("칸쿤 여행")
                .nightsAndDays(2, 3)
                .startDate(LocalDate.of(2020, 12, 9))
                .whereToStay("리조트")
                .addPlan(0, "체크인하고 짐 풀기")
                .addPlan(0, "저녁 식사")
                .getPlan();
    }

    public TourPlan longBeachTrip() {
        return tourPlanBuilder.title("롱비치")
                .startDate(LocalDate.of(2021, 7, 15))
                .getPlan();
    }
}
TourDirector director = new TourDirector(new DefaultTourBuilder());
TourPlan tourPlan = director.cancunTrip();
TourPlan tourPlan1 = director.longBeachTrip();

이때 cancunTrip()과 longBeachTrip()은 자주 반복되는 프로세스를 미리 선언해둔 메서드이다.

따라서 클라이언트는 해당 메서드들을 통해 특정 인스턴스를 바로 획득할 수가 있다. 당연히 다른 인스턴스를 생성할 수도 있다.

3. 장/단점

1) 장점

만들기 복잡한 객체를 순차적으로 만들 수 있는 프로세스를 제공한다.

입력한 필드값을 검증하는 로직을 넣을 수도 있다. 그렇기 때문에 클라이언트는 깔끔한 코드를 사용할 수 있게 된다.

 

또한 동일한 프로세스를 통해 각기 다른 객체를 만들 수도 있다.

TourDirector director = new TourDirector(new VipTourBuilder());

예를 들어 VipTourBuilder와 같이 다양한 빌더를 만들어서 제공함으로써 확장성을 가져갈 수 있다.

이때 내부적으로는 기존의 DefaultTourBuilder와는 다른 로직을 태울 수가 있게 된다.

2) 단점

특정 객체를 만들기 이전에 디렉터(혹은 빌더)를 먼저 만들어야 한다는 단점이 있다. 따라서 성능 이슈가 있을 수 있다.

또한 빌더 클래스를 생성함으로써 전체 구조가 조금 복잡해질 수 있다.