빌더 패턴

빌더 패턴(Builder pattern)이란 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다.

자바

/** "Product" */class Pizza {
private String dough = "";
private String sauce = "";
private String topping = "";

public void setDough(String dough) {
this.dough = dough;
}

public void setSauce(String sauce) {
this.sauce = sauce;
}

public void setTopping(String topping) {
this.topping = topping;
}}/** "Abstract Builder" */abstract class PizzaBuilder {
protected Pizza pizza;

public Pizza getPizza() {
return pizza;
}

public void createNewPizzaProduct() {
pizza = new Pizza();
}

public abstract void buildDough();

public abstract void buildSauce();

public abstract void buildTopping();}/** "ConcreteBuilder" */class HawaiianPizzaBuilder extends PizzaBuilder {
public void buildDough() {
pizza.setDough("cross");
}

public void buildSauce() {
pizza.setSauce("mild");
}

public void buildTopping() {
pizza.setTopping("ham+pineapple");
}}/** "ConcreteBuilder" */class SpicyPizzaBuilder extends PizzaBuilder {
public void buildDough() {
pizza.setDough("pan baked");
}

public void buildSauce() {
pizza.setSauce("hot");
}

public void buildTopping() {
pizza.setTopping("pepperoni+salami");
}}/** "Director" */class Cook {
private PizzaBuilder pizzaBuilder;

public void setPizzaBuilder(PizzaBuilder pizzaBuilder) {
this.pizzaBuilder = pizzaBuilder;
}

public Pizza getPizza() {
return pizzaBuilder.getPizza();
}

public void constructPizza() {
pizzaBuilder.createNewPizzaProduct();
pizzaBuilder.buildDough();
pizzaBuilder.buildSauce();
pizzaBuilder.buildTopping();
}}/** A given type of pizza being constructed. */public class BuilderExample {
public static void main(String[] args) {
Cook cook = new Cook();
PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();

cook.setPizzaBuilder(hawaiianPizzaBuilder);
cook.constructPizza();

Pizza pizza = cook.getPizza();
}}

C#

//Implementation in C#.class Pizza{
    string dough;
    string sauce;
    string topping;
    public Pizza() {}
    public void SetDough( string d){ dough = d;}
    public void SetSauce( string s){ sauce = s;}
    public void SetTopping( string t){ topping = t;}}//Abstract Builderabstract class PizzaBuilder{
    protected Pizza pizza;
    public PizzaBuilder(){}
    public Pizza GetPizza(){ return pizza; }
    public void CreateNewPizza() { pizza = new Pizza(); }

    public abstract void BuildDough();
    public abstract void BuildSauce();
    public abstract void BuildTopping();}//Concrete Builderclass HawaiianPizzaBuilder : PizzaBuilder{
    public override void BuildDough()   { pizza.SetDough("cross"); }
    public override void BuildSauce()   { pizza.SetSauce("mild"); }
    public override void BuildTopping() { pizza.SetTopping("ham+pineapple"); }}//Concrete Builderclass SpicyPizzaBuilder : PizzaBuilder{
    public override void BuildDough()   { pizza.SetDough("pan baked"); }
    public override void BuildSauce()   { pizza.SetSauce("hot"); }
    public override void BuildTopping() { pizza.SetTopping("pepparoni+salami"); }}/** "Director" */class Waiter {
    private PizzaBuilder pizzaBuilder;

    public void SetPizzaBuilder (PizzaBuilder pb) { pizzaBuilder = pb; }
    public Pizza GetPizza() { return pizzaBuilder.GetPizza(); }

    public void ConstructPizza() {
        pizzaBuilder.CreateNewPizza();
        pizzaBuilder.BuildDough();
        pizzaBuilder.BuildSauce();
        pizzaBuilder.BuildTopping();
    }}/** A customer ordering a pizza. */class BuilderExample{
    public static void Main(string[] args) {
        Waiter waiter = new Waiter();
        PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
        PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();

        waiter.SetPizzaBuilder ( hawaiianPizzaBuilder );
        waiter.ConstructPizza();

        Pizza pizza = waiter.GetPizza();
    }}

C++

// Implementation in C++.#include <iostream>#include <memory>#include <string>// Productclass 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 Builderclass PizzaBuilder{protected:
    std::auto_ptr<Pizza> pizza;public:
    PizzaBuilder() {}
    virtual ~PizzaBuilder() {}
    std::auto_ptr<Pizza> GetPizza() { return pizza; }

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

    virtual void buildDough()=0;
    virtual void buildSauce()=0;
    virtual void buildTopping()=0;};// ConcreteBuilderclass HawaiianPizzaBuilder : public PizzaBuilder{public:
    HawaiianPizzaBuilder() : PizzaBuilder() {}
    ~HawaiianPizzaBuilder(){}

    void buildDough() { pizza->SetDough("cross"); }
    void buildSauce() { pizza->SetSauce("mild"); }
    void buildTopping() { pizza->SetTopping("ham and pineapple"); }};// ConcreteBuilderclass 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"); }};// Directorclass Waiter{private:
    PizzaBuilder* pizzaBuilder;public:
    Waiter() : pizzaBuilder(NULL) {}
    ~Waiter() { }

    void SetPizzaBuilder(PizzaBuilder* b) { pizzaBuilder = b; }
    std::auto_ptr<Pizza> GetPizza() { return pizzaBuilder->GetPizza(); }
    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> pizza = waiter.GetPizza();
    pizza->ShowPizza();

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

    return EXIT_SUCCESS;}

비주얼 프롤로그

Product
interface pizza
   predicates
      setDough : (string Dough).
      setSauce : (string Sauce).
      setTopping : (string Topping).
end interface pizza
class pizza : pizza
end class pizza
implement pizza
   facts
      dough : string := "".
      sauce : string := "".
      topping : string := "".
   clauses
      setDough(Dough) :- dough := Dough.
   clauses
      setSauce(Sauce) :- sauce := Sauce.
   clauses
      setTopping(Topping) :- topping := Topping.
end implement pizza
Abstract Builder
interface pizzaBuilder
   predicates
      getPizza : () -> pizza Pizza.
      createNewPizzaProduct : ().
   predicates
      buildDough : ().
      buildSauce : ().
      buildTopping : ().
end interface pizzaBuilder
Visual Prolog does not support abstract classes, but we can create a support class instead:
interface pizzaBuilderSupport
   predicates from pizzaBuilder
      getPizza, createNewPizzaProduct
end interface pizzaBuilderSupport
class pizzaBuilderSupport : pizzaBuilderSupport
end class pizzaBuilderSupport
implement pizzaBuilderSupport
   facts
      pizza : pizza := erroneous.
   clauses
      getPizza() = pizza.
   clauses
      createNewPizzaProduct() :- pizza := pizza::new().
end implement pizzaBuilderSupport
ConcreteBuilder #1
class hawaiianPizzaBuilder :  pizzaBuilder
end class hawaiianPizzaBuilder
implement hawaiianPizzaBuilder
   inherits pizzaBuilderSupport

   clauses
      buildDough() :- getPizza():setDough("cross").
   clauses
      buildSauce() :- getPizza():setSauce("mild").
   clauses
      buildTopping() :- getPizza():setTopping("ham+pineapple").
end implement hawaiianPizzaBuilder
ConcreteBuilder #2
class spicyPizzaBuilder :  pizzaBuilder
end class spicyPizzaBuilder
implement spicyPizzaBuilder
   inherits pizzaBuilderSupport

   clauses
      buildDough() :- getPizza():setDough("pan baked").
   clauses
      buildSauce() :- getPizza():setSauce("hot").
   clauses
      buildTopping() :- getPizza():setTopping("pepperoni+salami").
end implement spicyPizzaBuilder
Director
interface waiter
   predicates
      setPizzaBuilder : (pizzaBuilder PizzaBuilder).
      getPizza : () -> pizza Pizza.
   predicates
      constructPizza : ().
end interface waiter
class waiter : waiter
end class waiter
implement waiter
   facts
      pizzaBuilder : pizzaBuilder := erroneous.
   clauses
      setPizzaBuilder(PizzaBuilder) :- pizzaBuilder := PizzaBuilder.
   clauses
      getPizza() = pizzaBuilder:getPizza().
   clauses
      constructPizza() :- 
         pizzaBuilder:createNewPizzaProduct(),
         pizzaBuilder:buildDough(),
         pizzaBuilder:buildSauce(),
         pizzaBuilder:buildTopping().
end implement waiter
A customer ordering a pizza.
goal
   Hawaiian_pizzabuilder = hawaiianPizzaBuilder::new(),
   Waiter = waiter::new(),
   Waiter:setPizzaBuilder(Hawaiian_pizzabuilder),
   Waiter:constructPizza(),
   Pizza = Waiter:getPizza().

펄

## Productpackage pizza;sub new {
    return bless {
        dough => undef,
        sauce => undef,
        topping => undef
    }, shift;}sub set_dough {
    my( $self, $dough ) = @_;
    $self->{dough} = $dough;}sub set_sauce {
    my( $self, $sauce ) = @_;
    $self->{sauce} = $sauce;}sub set_topping {
    my( $self, $topping ) = @_;
    $self->{topping} = $topping;}1;## Abstract builderpackage pizza_builder;sub new {
    return bless {
        pizza => undef
    }, shift;}sub get_pizza {
    my( $self ) = @_;
    return $self->{pizza};}sub create_new_pizza_product {
    my( $self ) = @_;
    $self->{pizza} = pizza->new;}# This is what an abstract method could look like in perl...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;## Concrete builderpackage 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;## Concrete builderpackage 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;## Directorpackage waiter;sub new {
    return bless {
        pizza_builder => undef
    }, shift;}sub set_pizza_builder {
    my( $self, $builder ) = @_;
    $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;## Lets order pizza (client of Director/Builder)package mainmy $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;