빌더 패턴이란 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다. **2 단어 요약 : 생성자 오버로딩**

## 예

### C++
// Implementation in C++.

// Product
class Pizza
private:
 std::string dough;
 std::string sauce;
 std::string topping;

public:
 Pizza { }
 ~Pizza { }

 void SetDough(const std::string& d) { dough = d; };
 void SetSauce(const std::string& s) { sauce = s; };
 void SetTopping(const std::string& t) { topping = t; }

 void ShowPizza
 std::cout << " Yummy !!!" << std::endl
 << "Pizza with Dough as " << dough
 << ", Sauce as " << sauce
 << " and Topping as " << topping
 << " !!! " << std::endl;

// Abstract Builder
class PizzaBuilder
protected:
 std::auto_ptr pizza;
public:
 PizzaBuilder {}
 virtual ~PizzaBuilder {}
 std::auto_ptr GetPizza { return pizza; }

 void createNewPizzaProduct { pizza.reset (new Pizza); }

 virtual void buildDough=0;
 virtual void buildSauce=0;
 virtual void buildTopping=0;

// ConcreteBuilder
class HawaiianPizzaBuilder : public PizzaBuilder
public:
 HawaiianPizzaBuilder : PizzaBuilder {}
 ~HawaiianPizzaBuilder{}

 void buildDough { pizza->SetDough("cross"); }
 void buildSauce { pizza->SetSauce("mild"); }
 void buildTopping { pizza->SetTopping("ham and pineapple"); }

// ConcreteBuilder
class SpicyPizzaBuilder : public PizzaBuilder
public:
 SpicyPizzaBuilder : PizzaBuilder {}
 ~SpicyPizzaBuilder {}

 void buildDough { pizza->SetDough("pan baked"); }
 void buildSauce { pizza->SetSauce("hot"); }
 void buildTopping { pizza->SetTopping("pepperoni and salami"); }

// Director
class Waiter
private:
 PizzaBuilder* pizzaBuilder;
public:
 Waiter : pizzaBuilder(NULL) {}
 ~Waiter { }

 void SetPizzaBuilder(PizzaBuilder* b) { pizzaBuilder = b; }
 std::auto_ptrGetPizza; }
 void ConstructPizza
 pizzaBuilder->createNewPizzaProduct;
 pizzaBuilder->buildDough;
 pizzaBuilder->buildSauce;
 pizzaBuilder->buildTopping;

// A customer ordering a pizza.
int main
 Waiter waiter;

 HawaiianPizzaBuilder hawaiianPizzaBuilder;
 waiter.SetPizzaBuilder (&hawaiianPizzaBuilder);
 waiter.ConstructPizza;
 std::auto_ptr pizza = waiter.GetPizza;
 pizza->ShowPizza;

 SpicyPizzaBuilder spicyPizzaBuilder;
 waiter.SetPizzaBuilder(&spicyPizzaBuilder);
 waiter.ConstructPizza;
 pizza = waiter.GetPizza;
 pizza->ShowPizza;

 return EXIT_SUCCESS;

### 비주얼 프롤로그
Product

  pizza
 
 setDough : .
 setSauce : .
 setTopping : .
  pizza

  pizza : pizza
  pizza

  pizza
 
 dough : string := .
 sauce : string := .
 topping : string := .
 
 setDough.
 
 setSauce.
 
 setTopping.
  pizza

Abstract Builder

  pizzaBuilder
 
 getPizza : .
 createNewPizzaProduct : .
 
 buildDough : .
 buildSauce : .
 buildTopping : .
  pizzaBuilder

Visual Prolog does not support abstract classes, but we can create a support class instead:

  pizzaBuilderSupport
  pizzaBuilder
 getPizza, createNewPizzaProduct
  pizzaBuilderSupport

  pizzaBuilderSupport : pizzaBuilderSupport
  pizzaBuilderSupport

  pizzaBuilderSupport
 
 pizza : pizza := .
 
 getPizza = pizza.
 
 createNewPizzaProduct.
  pizzaBuilderSupport

ConcreteBuilder #1

  hawaiianPizzaBuilder : pizzaBuilder
  hawaiianPizzaBuilder

  hawaiianPizzaBuilder
  pizzaBuilderSupport

 
 buildDough.
 
 buildSauce.
 
 buildTopping.
  hawaiianPizzaBuilder

ConcreteBuilder #2

  spicyPizzaBuilder : pizzaBuilder
  spicyPizzaBuilder

  spicyPizzaBuilder
  pizzaBuilderSupport

 
 buildDough.
 
 buildSauce.
 
 buildTopping.
  spicyPizzaBuilder

Director

  waiter
 
 setPizzaBuilder : .
 getPizza : .
 
 constructPizza : .
  waiter

  waiter : waiter
  waiter

  waiter
 
 pizzaBuilder : pizzaBuilder := .
 
 setPizzaBuilder.
 
 getPizza.
 
 constructPizza :- 
 pizzaBuilder:createNewPizzaProduct,
 pizzaBuilder:buildDough,
 pizzaBuilder:buildSauce,
 pizzaBuilder:buildTopping.
  waiter

A customer ordering a pizza.

 
 ,
 ,
 ,
 ,
 .

### 펄
package pizza;

sub new {
 return bless {
 dough => undef,
 sauce => undef,
 topping => undef

sub set_dough {
 my = @_;
 $self->{dough} = $dough;

sub set_sauce {
 my = @_;
 $self->{sauce} = $sauce;

sub set_topping {
 my = @_;
 $self->{topping} = $topping;

1;

package pizza_builder;

sub new {
 return bless {
 pizza => undef

sub get_pizza {
 my( $self ) = @_;
 return $self->{pizza};

sub create_new_pizza_product {
 my( $self ) = @_;
 $self->{pizza} = pizza->new;

sub build_dough {
 croak("This method must be overridden.");

sub build_sauce {
 croak("This method must be overridden.");

sub build_topping {
 croak("This method must be overridden.");

1;

package hawaiian_pizza_builder;

use base qw{ pizza_builder };

sub build_dough {
 my( $self ) = @_;
 $self->{pizza}->set_dough("cross");

sub build_sauce {
 my( $self ) = @_;
 $self->{pizza}->set_sauce("mild");

sub build_topping {
 my( $self ) = @_;
 $self->{pizza}->set_topping("ham+pineapple");

1;

package spicy_pizza_builder;

use base qw{ pizza_builder };

sub build_dough {
 my( $self ) = @_;
 $self->{pizza}->set_dough("pan baked");

sub build_sauce {
 my( $self ) = @_;
 $self->{pizza}->set_sauce("hot");

sub build_topping {
 my( $self ) = @_;
 $self->{pizza}->set_topping("pepperoni+salami");

1;

package waiter;

sub new {
 return bless {
 pizza_builder => undef

sub set_pizza_builder {
 my = @_;
 $self->{pizza_builder} = $builder;

sub get_pizza {
 my( $self ) = @_;
 return $self->{pizza_builder}->get_pizza;

sub construct_pizza {
 my( $self ) = @_;
 $self->{pizza_builder}->create_new_pizza_product;
 $self->{pizza_builder}->build_dough;
 $self->{pizza_builder}->build_sauce;
 $self->{pizza_builder}->build_topping;

1;

package main

my $waiter = waiter->new;
my $hawaiian_pb = hawaiian_pizza_builder->new;
my $spicy_pb = spicy_pizza_builder->new;

$waiter->set_pizza_builder( $hawaiian_pb );
$waiter->construct_pizza;

my $pizza = $waiter->get_pizza;

print "Serving a nice pizza with:\n";
for (keys %$pizza) {
 print " $pizza->{$_} $_\n";

1;

### PHP
/** Product **/
class Pizza{
 private $dough;
 private $sauce;
 private $topping;
 public function setDough($dough){
 $this->dough = $dough;
 public function setSauce($sauce){
 $this->sauce = $sauce;
 public function setTopping($topping){
 $this->topping = $topping;

/** Abstract builder **/
abstract class PizzaBuilder{
 protected $pizza;
 public function __construct{
 $this->pizza = new Pizza;
 public function getPizza{
 return $this->pizza;
 abstract function buildDough;
 abstract function buildSauce;
 abstract function buildTopping;

/** Concrete builder **/
class SpicyPizza extends PizzaBuilder{
 public function buildDough{
 $this->pizza->setDough('crispy');
 public function buildSauce{
 $this->pizza->setSauce('hot');
 public function buildTopping{
 $this->pizza->setTopping('pepperoni+salami');

/** Director **/
class Chef{
 private $pizza_builder;
 public function setPizzaBuilder(PizzaBuilder $pizza_builder){
 $this->pizza_builder = $pizza_builder;
 public function cookPizza{
 $this->pizza_builder->buildDough;
 $this->pizza_builder->buildSauce;
 $this->pizza_builder->buildTopping;
 public function getPizza{
 return $this->pizza_builder->getPizza;

//Customer orders a Pizza.
$chef = new Chef;

$order = new SpicyPizza;
$chef->setPizzaBuilder($order);
$chef->cookPizza;
$pizza = $chef->getPizza;

print_r($pizza);