Builder pattern

From Wikipedia, the free encyclopedia

Jump to: navigation, search

The Builder Pattern is a software design pattern. The intention is to abstract steps of construction of objects so that different implementations of these steps can construct different representations of objects.

Often, the Builder Pattern is used to build Products in accordance to the Composite pattern, a structure pattern.

Contents

[edit] Class Diagram

Builder Structure

[edit] Builder

Abstract interface for creating objects (product).

[edit] Concrete Builder

Provide implementation for Builder. Construct and assemble parts to build the objects.

[edit] Director

The Director class is responsible for managing the correct sequence of object creation. It receives a Concrete Builder as a parameter and executes the necessary operations on it.

[edit] Product

The final object that will be created by the Director using Builder.

[edit] Useful tips

  • Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.
  • Builder often builds a Composite.
  • Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.
  • Sometimes creational patterns are complementary: Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototype can use Singleton in their implementations.

[edit] Examples

[edit] Java

/** "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 pb) {
		pizzaBuilder = pb;
	}
 
	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();
	}
}

[edit] C#

//Implementation in C#.
class Pizza
{
    string dough;
    string sauce;
    string topping;
    public string Dough   { get { return dough; }   set { dough = value; } }
    public string Sauce   { get { return sauce; }   set { sauce = value; } }
    public string Topping { get { return topping; } set { topping = value; } }
    public override string ToString() {
        return string.Format(
                "Pizza with Dough as {0}, Sauce as {1} and Topping as {2}",
                Dough,
                Sauce,
                Topping);
    }
}
 
//Abstract Builder
abstract class PizzaBuilder
{
    protected Pizza pizza;
    public Pizza Pizza { get { 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.Dough   = "cross"; }
    public override void BuildSauce()   { pizza.Sauce   = "mild"; }
    public override void BuildTopping() { pizza.Topping = "ham+pineapple"; }
}
 
//Concrete Builder
class SpicyPizzaBuilder : PizzaBuilder
{
    public override void BuildDough()   { pizza.Dough   = "pan baked"; }
    public override void BuildSauce()   { pizza.Sauce   = "hot"; }
    public override void BuildTopping() { pizza.Topping = "pepparoni+salami"; }
}
 
/** "Director" */
class Waiter {
    private PizzaBuilder pizzaBuilder;
 
    public PizzaBuilder PizzaBuilder { get { return pizzaBuilder; } set { pizzaBuilder = value; } }
    public Pizza Pizza { get { return pizzaBuilder.Pizza; } }
 
    public void ConstructPizza() {
        pizzaBuilder.CreateNewPizza();
        pizzaBuilder.BuildDough();
        pizzaBuilder.BuildSauce();
        pizzaBuilder.BuildTopping();
    }
}
 
public class TestPizza {
    private static void BuildAndDisplayPizza(Waiter waiter) {
        waiter.ConstructPizza();
        System.Console.WriteLine(waiter.Pizza);
    }
 
    public static void Main() {
        Waiter waiter = new Waiter();
 
        waiter.PizzaBuilder = new HawaiianPizzaBuilder();
        BuildAndDisplayPizza(waiter);
 
        waiter.PizzaBuilder = new SpicyPizzaBuilder();
        BuildAndDisplayPizza(waiter);
    }
}

[edit] 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 two 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;
}

[edit] Visual Prolog

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().

[edit] perl

## 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;

[edit] 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('thin');
  }
  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);

[edit] External links


Personal tools