본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.

빌더 패턴(Builder Pattern)은 여러 부분으로 이루어진 복잡한 객체를 만드는 과정을 단계별로 나누고, 같은 생성 절차로 서로 다른 표현의 객체를 만들 수 있게 객체의 생성과 표현을 분리하는 GoF 생성 패턴이다.

생성자 하나로 객체를 만들려면 부품이 많을수록 매개변수가 길어지고, 순서나 생략 여부에 따라 생성자를 여러 개 두어야 한다. 빌더 패턴은 객체를 한 번에 만들지 않고, 빌더(Builder) 객체에 부품을 하나씩 만들어 붙이게 한 뒤 마지막에 완성품을 꺼낸다. 건축가가 같은 설계 순서로 블록을 조립하더라도 어떤 블록을 쓰느냐에 따라 다른 건물이 나오는 것에 비유된다.

GoF 는 23개 패턴을 목적에 따라 생성·구조·행위로 나누는데, 빌더는 객체를 만드는 방법을 다루므로 팩토리 메서드, 추상 팩토리, 프로토타입, 싱글톤과 함께 생성 패턴에 속한다. 구조 패턴(어댑터·브리지·컴포지트·데코레이터·퍼사드·플라이웨이트·프록시)이 아니다.

역할 설명
Builder 부품을 만드는 단계별 메서드(buildPartA, buildPartB …)를 선언한 인터페이스
ConcreteBuilder Builder 를 구현해 실제 부품을 만들고 조립하며, 완성품을 돌려주는 메서드(getResult)를 가진다
Director Builder 의 메서드를 정해진 순서로 불러 생성 절차를 진행한다. 어떤 ConcreteBuilder 를 쓰는지는 모른다
Product 만들어지는 복잡한 객체

Director 가 같은 순서로 단계를 부르더라도, 텍스트 문서를 만드는 빌더를 넘기면 텍스트가, HTML 을 만드는 빌더를 넘기면 HTML 문서가 나온다. 생성 절차와 결과의 표현이 분리되어 있기 때문이다.

자바에서는 매개변수가 많은 객체를 만들 때 메서드를 이어 부르는 빌더를 흔히 쓴다.

public class Pizza {
    private final String size;      // 필수
    private final boolean cheese;   // 선택
    private final boolean bacon;    // 선택

    private Pizza(Builder b) {
        this.size = b.size;
        this.cheese = b.cheese;
        this.bacon = b.bacon;
    }

    public static class Builder {
        private final String size;
        private boolean cheese, bacon;

        public Builder(String size) { this.size = size; }
        public Builder cheese() { this.cheese = true; return this; }
        public Builder bacon()  { this.bacon = true;  return this; }
        public Pizza build()    { return new Pizza(this); }
    }
}

// 사용: 필요한 부품만 골라 단계적으로 조립하고 마지막에 build()
Pizza p = new Pizza.Builder("L").cheese().bacon().build();
  • 매개변수가 많아도 무엇을 넣는지 이름으로 드러나 읽기 쉽다
  • 완성된 객체는 필드를 바꾸지 않는 불변 객체로 만들기 쉽다
  • 자바의 StringBuilder 처럼 조금씩 덧붙인 뒤 마지막에 결과를 꺼내는 클래스도 같은 생각이다

다른 생성 패턴과 비교

편집 원본 편집
패턴 무엇을 결과를 돌려주는 시점
빌더 복잡한 객체 하나를 여러 단계로 조립 모든 단계가 끝난 뒤(getResult, build)
추상 팩토리 서로 관련된 객체 여러 개(제품군)를 구체 클래스 없이 생성 메서드를 부를 때마다 바로
팩토리 메서드 어떤 클래스의 객체를 만들지 하위 클래스가 결정 메서드를 부를 때 바로
프로토타입 원본 객체를 복제해 생성 복제할 때 바로
싱글톤 인스턴스를 하나만 만들고 공유 처음 요청할 때 한 번
  • 생성 과정을 단계별로 통제할 수 있고, 같은 절차로 다른 표현을 만들 수 있다
  • 생성 코드와 표현 코드가 분리되어 새 표현을 추가할 때 ConcreteBuilder 만 더하면 된다
  • 클래스(빌더)가 늘어나 단순한 객체에는 오히려 번거롭다