빌더 패턴은 복잡한 객체의 생성 과정과 그 표현 방식을 분리함으로써, 동일한 생성 절차로 다양한 형태의 객체를 만들 수 있도록 해주는 디자인 패턴이다. 이는 생성 로직이 일정하지만, 구성 요소의 세부 사항이 다양할 때 유용하다.
주로 다음과 같은 상황에서 적용된다:
- 객체의 생성 순서는 고정되지만, 각 부분의 구현 방식은 다를 때
- 클라이언트가 '무엇을 만들고 싶은지'만 지정하면 되도록 추상화하고자 할 때
핵심 구성 요소 중 하나인 디렉터(Director)는 생성 흐름을 관리하며, 사용자와 실제 생성 로직 사이의 결합도를 낮춘다. 이를 통해 클라이언트 코드는 구체적인 생성 세부사항을 알 필요 없이 간단히 결과물을 얻을 수 있다.
예시: 간단한 인물 도형 그리기
abstract class CharacterBuilder
{
protected Graphics canvas;
protected Pen stroke;
public CharacterBuilder(Graphics canvas, Pen stroke)
{
this.canvas = canvas;
this.stroke = stroke;
}
public abstract void ConstructHead();
public abstract void ConstructTorso();
public abstract void ConstructLeftArm();
public abstract void ConstructRightArm();
public abstract void ConstructLeftLeg();
public abstract void ConstructRightLeg();
}
class SlimCharacterBuilder : CharacterBuilder
{
public SlimCharacterBuilder(Graphics canvas, Pen stroke) : base(canvas, stroke) { }
public override void ConstructHead()
{
canvas.DrawEllipse(stroke, 50, 20, 30, 30);
}
public override void ConstructTorso()
{
canvas.DrawRectangle(stroke, 60, 50, 10, 50);
}
public override void ConstructLeftArm()
{
canvas.DrawLine(stroke, 60, 50, 40, 100);
}
public override void ConstructRightArm()
{
canvas.DrawLine(stroke, 70, 50, 90, 100);
}
public override void ConstructLeftLeg()
{
canvas.DrawLine(stroke, 60, 100, 45, 150);
}
public override void ConstructRightLeg()
{
canvas.DrawLine(stroke, 70, 100, 85, 150);
}
}
class CharacterDirector
{
private CharacterBuilder builder;
public CharacterDirector(CharacterBuilder builder)
{
this.builder = builder;
}
public void AssembleCharacter()
{
builder.ConstructHead();
builder.ConstructTorso();
builder.ConstructLeftArm();
builder.ConstructRightArm();
builder.ConstructLeftLeg();
builder.ConstructRightLeg();
}
}
사용 예시:
Pen outline = new Pen(Color.Yellow);
CharacterBuilder slim = new SlimCharacterBuilder(pictureBox1.CreateGraphics(), outline);
CharacterDirector directorSlim = new CharacterDirector(slim);
directorSlim.AssembleCharacter();
CharacterBuilder fat = new FatCharacterBuilder(pictureBox2.CreateGraphics(), outline);
CharacterDirector directorFat = new CharacterDirector(fat);
directorFat.AssembleCharacter();
C++ 버전 구현:
#include <iostream>
using namespace std;
class Builder
{
public:
virtual void BuildHead() {}
virtual void BuildTorso() {}
virtual void BuildLeftArm() {}
virtual void BuildRightArm() {}
virtual void BuildLeftLeg() {}
virtual void BuildRightLeg() {}
};
class LeanBuilder : public Builder
{
public:
void BuildHead() { cout << "슬림 헤드 생성" << endl; }
void BuildTorso() { cout << "슬림 몸통 생성" << endl; }
void BuildLeftArm() { cout << "슬림 왼팔 생성" << endl; }
void BuildRightArm() { cout << "슬림 오른팔 생성" << endl; }
void BuildLeftLeg() { cout << "슬림 왼다리 생성" << endl; }
void BuildRightLeg() { cout << "슬림 오른다리 생성" << endl; }
};
class Director
{
private:
Builder* builder;
public:
Director(Builder* b) : builder(b) {}
void CreateCharacter()
{
builder->BuildHead();
builder->BuildTorso();
builder->BuildLeftArm();
builder->BuildRightArm();
builder->BuildLeftLeg();
builder->BuildRightLeg();
}
};
int main()
{
LeanBuilder lean;
Director director(&lean);
director.CreateCharacter();
return 0;
}