28 Jul 2019

디자인 패턴 02 - 빌더 (Builder)

빌더 패턴은 복잡한 객체를 생성하는 방법과 표현하는 방법을 정의하는 클래스를 별도로 분리하여, 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공하는 패턴이다.

빌더 패턴의 핵심은 객체를 생성하는 과정과 객체를 표현하는 방법을 분리하여 다양한 생성 절차에서 서로 다른 표현 결과(객체)를 만들 수 있게 하여 객체 생성하는 것을 유연하게 구현하자는 것이다.

00.png

위와 같이 Director는 Builder 인터페이스를 활용하여 특정한 복합 객체를 생성한다. Director는 객체를 생성하는 절차를 구현하고, 이 절차로부터 요청받아 생성할 객체를 만들고 표현하는 책임은 Builder 인터페이스를 구현하는 구체 빌더 클래스에게 위임하는 것이다. 구체 빌더 클래스들은 복잡한 객체를 생성하고 조립하는데 필요한 매커니즘을 Builder 인터페이스에 정의된 각 연산에서 구현한다.

Builder 인터페이스에서는 객체를 합성하기 위한 연산들에 대해 추상 메서드나 가상 함수(C++)로 구현할 필요는 없다. 그냥 구현부만 비어두면 된다. 서브 클래스인 여러 구체 빌더 클래스들이 자신이 생성해야 될 객체를 만들기 위한 연산만 선택적으로 정의하기 위해서이다. 필요없다면 구현하지 않으면 된다.

빌더 패턴을 통해 복잡한 객체를 표현하는 방법을 별도의 모듈로 정의할 수 있고, 사용자는 이를 알 필요없이 빌더와 상호작용을 통해 필요한 객체를 생성할 수 있다.

보통 이 패턴을 사용할 때는 다음과 같은 순서로 객체를 생성해낸다.


01.png

  1. 사용자는 Director 및 Builder를 생성한다.
  2. Director는 필요한 객체의 일부 요소, 파라미터를 Builder로 전달한다.
    • Director는 객체를 생성하는 절차, 순서, 방식만 구현한다.
  3. Builder는 Director의 요청을 받아, 전달받은 요소를 객체에 합성한다.
    • Builder는 Director의 요청을 받아 객체에 요소를 합성하도록 구현된다.
  4. 사용자는 Director로 요청하여 완성된 객체를 가져온다.
    • 구현하기에 따라 빌더로 직접 요청할 수도 있다.

빌더 패턴을 사용할 때, 필요한 객체 생성 / 복합 방법이 바뀐다면 Builder 인터페이스를 구현하는 다른 구체 빌더 클래스를 정의하여 사용하면 된다. Director는 Builder 인터페이스에 정의된 연산을 통해 상호작용만 하여 필요한 객체를 생성할 뿐이다.

또한 Builder 인터페이스에는 객체를 완성하기 전(getProduct)에, 호출할 수 있는 여러 연산(builderPartA, builderPartB와 같은)이 있는데, Director에서는 이런 연산들 중 필요없는 연산이 있으면 호출하지 않을 수도 있고 순서도 바꿀 수도 있다. 따라서 Director 입장에서는 객체를 생성하는 절차를 세밀하게 조정이 가능하다.

Director와 Builder를 통해 각자의 책임을 분리함으로써 우리는 여러 객체의 생성 방식을 유연하게 결정할 수 있다. 객체 생성 과정이나 방식이 바뀌면 (일부 파라미터만 사용한다든지) 다른 Director를 사용하면 되고, 필요한 객체가 바뀌면 Builder만 바꾸면 된다.

이는 객체 생성 방식이 여러 방법일 경우에 특히 유용하다. 예를 들어 어느 클래스의 인스턴스 생성 방식이 매우 다양할 경우 이 빌더 패턴을 적용시킬 수 있다.

Builder Example

빌더 패턴은 복잡한 객체의 단계별 생성에 중점을 둔 반면에, 추상 팩토리 패턴은 객체의 집합이 존재할 때 유연한 설계에 중점을 둔 것이다.


Tags:
Stats:
0 comments