Design patterns 04.

Creational patterns - Builder

by Dichter
빌더(Builder)란?

우선 에릭 감마를 비롯한 4인방이 소개하는 빌더의 의도, 동기 그리고 활용을 읽어보자. 어렵지 않은 단어와 문장이니, 의미를 보며 정독해보자.


Intent

Separate the construction of a complex object from its representation so that the same construction process can create different representations.


Motivation

A reader for the RTF (Rich Text Format) document exchange format should be able to convert RTF to many text formats. The reader might convert RTF documents into plain ASCII text or into a text widget that can be edited interactively. The problem, however, is that the number of possible conversions is open-ended. So it should be easy to add a new conversion without modifying the reader.

A solution is to configure the RTFReader class with a TextConverter object that converts RTF to another textual representation. Whenever the RTDReader recongnizes an RTFtoken (either plain text or an RTFcontrol word), it issues a requeset to the TextConverter to convert the token. TextConverter objects are responsible both for performing the data conversion and for representing the token in a particular format.

Subclasses of TextConverter specialize in different conversions and formats. Each kind of converter class takes the mechanism for creating and assembling a complex object and puts it behind an abstract interface. The converter is separate from the reader, which is resposible for parsing an RTF document.


The Builder pattern captures all these relationships. Each converter class is called a builder in the pattern, and the reader is called the director. Applied to this example, the Builder patterns separates the algorithm for interpreting a textual format (that is, the parer for RTF documents) from how a converted format gets created and represented. This lets us reuse the RTFReader's parsing algorithm to create different text representations from RTD documents - just configure the RTFReader with different subclasses of TextConverter.


Applicability

Use the Builder patterns when

the algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled.

the construction process must allow different representations for the object that's constructed.


설명에서는 RTF 리더(Reader)를 예시로 들고 있다. 사용자(개발자)가 리더를 이용하여 RTF를 여러 가지 포맷으로 변환하고 싶은 상황이다. 이때 변환을 도와주는 텍스트 컨버터(Text converter) 객체를 생성할 때에 빌더 패턴을 사용하였다.


여기서 주요 관점은 새로운 포맷 변환이 요구사항이 언제든지 추가될 수 있으며, 코드 종북과 의존성을 최대한 없애기 위해 RTF 리더의 파싱 알고리즘과 텍스트 컨버터의 컨버터 알고리즘을 분리시켜야 한다.


우선 왜 추상 팩토리를 사용하지 않았을까? RTF 리더는 여러 종류의 텍스트 컨버터를 사용하면서, 동시에 컨버터 별 특수한 기능들도 사용하고 싶다. 다만, 컨버터가 생성되는 과정만 추상화하고 싶다. 이때 추상 팩토리는 모든 팩토리가 동일한 메서드만을 포함하도록 추상 클래스로 정의되어 있기에, 서로 다른 기능들을 추가하기 어렵다.


구체 텍스트 컨버터 클래스(구체 빌더 클래스)는 추상 텍스트 컨버터(추상 빌더 클래스)가 정의하는 기본 메서드를 포함하고, 그 이외의 메서드도 정의할 수 있다. 이러한 구체 빌더 클래스를 이용하여 RTF 리더(구체 디렉터 클래스)는 기본 메서드 이외에도 다양한 메서드를 활용할 수 있다.


빌더 예제

생성 패턴을 설명하는 글에서 보여줬던 Maze 예제를 추상 팩토리를 이용하여 리펙토링 해보자. (코드를 삽입할 수 있는 수단이 없어, GitHub 링크로 대체하였다.)

Builder example code link


추상 팩토리와 마찬가지로 기존 Maze 코드에 새로운 요구사항이 추가된 상황이다. 기존 Maze 이외에도 사용자(개발자)가 선택할 수 있는 다양한 기능의 Maze를 추가하려고 한다. Maze를 구성할 수 있는 기존 빌더 이외에도 Maze의 총 Door의 개수를 알 수 있는 기능을 갖춘 빌더를 만들어보자.


Room, Door 그리고 Wall를 구성할 수 있는 기존 기능을 추상 빌더 클래스를 먼저 만들어준다. 그리고 추가 기능들을 다양한 빌더들을 추상 빌더 클래스를 상속하여 구현해준다.


사용자는 자기가 필요한 빌더를 이용하여 Maze를 구성해주고, 해당 빌더가 제공하는 기능들을 조회할 수 있다.


피터르 브뤼헐눈 속의 사냥꾼
이 작품은 일 년을 묘사한 여섯 작품 중 하나이다. 현재는 오스트리아 빈 미술사 박물관에 전시되고 있다. 이 그림은 북부 르네상스 운동의 영향을 받았다.


1쇄. 2020.12.06.

keyword
작가의 이전글Design Patterns 03.