빌더 패턴

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

구조

[편집]

[편집]

자바

[편집]
/** "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 Builder abstract 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 Builder class 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 Builder class 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>  // 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> 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; };  // 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_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(). 

[편집]
## Product package 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 builder package 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 builder 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;   ## Concrete builder 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;   ## Director package 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 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); 

같이 보기

[편집]