빌더 패턴
소프트웨어 디자인 패턴
(Builder 패턴에서 넘어옴)
빌더 패턴이란 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다. 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);