theory/디자인패턴

GoF의 디자인 패턴. 생성패턴 2.빌더

아르르르를를르 2021. 8. 15. 17:32

- 지난 글에 이어 생성패턴을 다뤄본다.

추상 팩토리 (Abstract Factory)

빌더 (Builder)

팩토리 메서드 (Factory Methods)

프로토타입 (Prototype)

싱글턴 (Singleton)

 


빌더 (Builder)

- 의도

복잡한 객체를 생성하는 클래스와 표현하는 클래스를 분리하여, 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공한다.

 

- 동기

생성과 표현의 분리를 통한 책임 분리

 

- 활용성

  • 복합 객체의 생성 알고리즘이 이른 합성하는 요소 객체들이 무엇인지 이들의 조립 방법에 독립적일 때
  • 합성할 객체들의 표현이 서로 다르더라도 생성 절차에서 이를 지원해야 할 때

 

- 구조

- 참여자

  • Builder: Product 객체의 일부 요소를 생성하기 위한 추상 인터페이스 정의
  • ConcreteBuilder: Builder 클래스에 정의된 인터페이스를 구현하며, 제품의 부품들을 모아 빌더를 복합
    • 제품 내부 표현을 구축하고 복합 객체가 어떻게 구성되는지에 관한 절차 정의
  • Director: Builder 인터페이스를 사용하는 객체를 합성
  • Product: 생성할 복합 객체를 표현

 

- 협력 방법

- 결과

  • 제품에 대한 내부 표현을 다양하게 변화할 수 있다.
    • Builder에 정의된 추상클래스를 통해 사용자가 동작하기 때문에, 새로운 제품의 표현 방법이나 복합 방법이 바뀔 때 Builder 클래스에서 상속을 통해 새로운 서브클래스를 정의하면 된다.
  • 생성과 표현에 필요한 코드를 분리한다.
  • 복합 객체를 생성하는 절차를 좀더 세밀하게 나눌 수 있다.
    • Director의 통제 아래 하나씩 내부 구성요소들을 만들어 나가기에 생성하는 과정 자체가 반영되어 있다.

 

- 구현

  1. 조합과 구축에 필요한 인터페이스를 정의
  2. 제품에 대한 추상 클래스는 필요없다.
    1. 제품은 Builder의 서브클래스로 생성되는데, 이 서브클래스 사이에 공통점이 없기 때문이다
  3. Builder에 있는 메서드의 구현부는 비워둔다.

 

- 예제

추상 클래스인 PhoneBuilder에서 Director가 요청하는 build 연산을 정의한다.

PhoneBuilder를 상속받은 ConcreteBuilder(AppleBuilder, GalaxyBuilder)가 필요한 표현을 override한다.

ConcreteBuilder는 Phone의 부품들을 조립하고 Director는 조립이 완성된 Phone을 반환한다.

 

AppleBuilder

Director director = new Director();
AppleBuilder appleBuilder = new AppleBuilder();

director.setPhoneBuilder(appleBuilder);

Phone phone = director.constructPhone();
System.out.println(phone);

 

Builder

package builder;

import product.Phone;

public abstract class PhoneBuilder {
    protected Phone phone;

    public Phone getPhone() {
        return phone;
    }

    public PhoneBuilder create() {
        phone = new Phone();
        return this;
    }

    public abstract PhoneBuilder buildName();
    public abstract PhoneBuilder buildCamera();
    public abstract PhoneBuilder buildCPU();
    public abstract PhoneBuilder buildDisplay();
}

 

ConcreteBuilder

package builder;

public class AppleBuilder extends PhoneBuilder {
    @Override
    public PhoneBuilder buildName() {
        toy.setName("Apple");
        return this;
    }

    @Override
    public PhoneBuilder buildCamera() {
        toy.setCamera("Camera");
        return this;
    }

    @Override
    public PhoneBuilder buildCPU() {
        toy.setCPU("A12 bionic");
        return this;
    }

    @Override
    public PhoneBuilder buildDisplay() {
        return this;
    }
}

 

Director

package director;

import builder.PhoneBuilder;
import product.Phone;

public class Director {
    private PhoneBuilder phoneBuilder;

    public void setPhoneBuilder(PhoneBuilder phoneBuilder) {
        this.phoneBuilder = phoneBuilder;
    }

    public Phone constructPhone() {
        return phoneBuilder.create()
                .buildName()
                .buildCamera()
                .buildCPU()
                .buildDisplay()
                .getPhone();
    }
}

 

Main

import builder.AppleBuilder;
import builder.GalaxyBuilder;
import director.Director;
import product.Phone;

public class Main {
    public static void main(String[] args) {
        Director director = new Director();

        AppleBuilder appleBuilder = new AppleBuilder();
        GalaxyBuilder galaxyBuilder = new GalaxyBuilder();

        director.setPhoneBuilder(appleBuilder);
        Phone iphone = director.constructPhone();
        System.out.println(iphone);
        
        director.setPhoneBuilder(galaxyBuilder);
        Phone samsungPhone = director.constructPhone();
        System.out.println(samsungPhone);
    }
}

 

- 관련 패턴과의 비교

빌더 패턴: 복잡한 객체의 단계별 생성에 중점. 생성 마지막 단계에서 생성한 제품을 반환

추상 팩토리 패턴: 제품의 유사군이 존재할 시 유연한 설계, 만드는 즉시 제품 반환

 

- 참고 문헌

  • GoF의 디자인 패턴(개정판) / 에릭 감마, 리처드 헬름, 랄프 존슨, 존 블라시디스 공저 / 김정아 역 / 프로텍미디어 / 발행 2015년 03월 26일