Builder pattern

From Wikipedia, the free encyclopedia
Jump to: navigation, search

The builder pattern is an object creation 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 with the composite pattern.

Contents

Definition [edit]

The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so, the same construction process can create different representations. [1]

Structure [edit]

Builder Structure
Builder
Abstract interface for creating objects (product).
Concrete Builder
Provides implementation for Builder. It is an object able to construct other objects. Constructs and assembles parts to build the objects.

Useful tips [edit]

  • 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 are built. Abstract Factory, Builder, and Prototype can use Singleton in their implementations.
  • Builders are good candidates for a fluent interface.

Examples [edit]

Java [edit]

 /** "Product" */
class Pizza {
 private String dough = "";
 private String sauce = "";
 private String topping = "";
 
 public void setDough(final String dough) {
  this.dough = dough;
 }
 
 public void setSauce(final String sauce) {
  this.sauce = sauce;
 }
 
 public void setTopping(final String topping) {
  this.topping = topping;
 }
}
 
 
 /** "Abstract Builder" */
abstract class PizzaBuilder {
 protected Pizza pizza;
 
 public abstract void buildDough();
 public abstract void buildSauce();
 public abstract void buildTopping();
 
 public void createNewPizzaProduct() {
  this.pizza = new Pizza();
 }
 
 public Pizza getPizza() {
  return this.pizza;
 }
}
 
 
 /** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
 @Override public void buildDough() {
  this.pizza.setDough("cross");
 }
 
 @Override public void buildSauce() {
  this.pizza.setSauce("mild");
 }
 
 @Override public void buildTopping() {
  this.pizza.setTopping("ham+pineapple");
 }
}
 
 /** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {
 @Override public void buildDough() {
  this.pizza.setDough("pan baked");
 }
 
 @Override public void buildSauce() {
  this.pizza.setSauce("hot");
 }
 
 @Override public void buildTopping() {
  this.pizza.setTopping("pepperoni+salami");
 }
}
 
 
 /** "Director" */
class Waiter {
 private PizzaBuilder pizzaBuilder;
 
 public void setPizzaBuilder(final PizzaBuilder pb) {
  this.pizzaBuilder = pb;
 }
 
 public Pizza getPizza() {
  return this.pizzaBuilder.getPizza();
 }
 
 public void constructPizza() {
  this.pizzaBuilder.createNewPizzaProduct();
  this.pizzaBuilder.buildDough();
  this.pizzaBuilder.buildSauce();
  this.pizzaBuilder.buildTopping();
 }
}
 
 
 /** A customer ordering a pizza. */
class BuilderExample {
 
 public static void main(final String[] args) {
 
  final Waiter waiter = new Waiter();
 
  final PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
  final PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();
 
  waiter.setPizzaBuilder(hawaiianPizzaBuilder);
  waiter.constructPizza();
 
  final Pizza pizza = waiter.getPizza();
 
  waiter.setPizzaBuilder(spicyPizzaBuilder);
  waiter.constructPizza();
 
  final Pizza anotherPizza = waiter.getPizza();
 }
}

C# [edit]

using System;
 
namespace BuilderPattern
{
  // Builder - abstract interface for creating objects (the product, in this case)
  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();
  }
  // Concrete Builder - provides implementation for Builder; an object able to construct other objects.
  // Constructs and assembles parts to build the objects
  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 - provides implementation for Builder; an object able to construct other objects.
  // Constructs and assembles parts to build the objects
  class SpicyPizzaBuilder : PizzaBuilder
  {
    public override void BuildDough()
    {
      pizza.dough = "pan baked";
    }
 
    public override void BuildSauce()
    {
      pizza.sauce = "hot";
    }
 
    public override void BuildTopping()
    {
      pizza.topping = "pepperoni + salami";
    }
  }
 
  // Director - responsible for managing the correct sequence of object creation.
  // Receives a Concrete Builder as a parameter and executes the necessary operations on it.
  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();
    }
  }
 
  // Product - The final object that will be created by the Director using Builder
  public class Pizza
  {
    public string dough = string.Empty;
    public string sauce = string.Empty;
    public string topping = string.Empty;
  }
 
  class Program
  {
    static void Main(string[] args)
    {
      PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
      Cook cook = new Cook();
      cook.SetPizzaBuilder(hawaiianPizzaBuilder);
      cook.ConstructPizza();
      // create the product
      Pizza hawaiian = cook.GetPizza();
 
      PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();
      cook.SetPizzaBuilder(spicyPizzaBuilder);
      cook.ConstructPizza();
      // create another product
      Pizza spicy = cook.GetPizza();
    }
  }
 
}

C++ [edit]

#include <string>
#include <iostream>
using namespace std;
 
// "Product"
class Pizza {
public:
        void dough(const string& dough) {
                dough_ = dough;
        }
 
        void sauce(const string& sauce) {
                sauce_ = sauce;
        }
 
        void topping(const string& topping) {
                topping_ = topping;
        }
 
        void open() const {
                cout << "Pizza with " << dough_ << " dough, " << sauce_ << " sauce and "
                        << topping_ << " topping. Mmm." << endl;
        }
 
private:
        string dough_;
        string sauce_;
        string topping_;
};
 
// "Abstract Builder"
class PizzaBuilder {
public:
       // Chinmay Mandal : This default constructor may not be required here
        PizzaBuilder()
        {
           // Chinmay Mandal : Wrong syntax
           // pizza_ = new Pizza;
        } 
        const Pizza& pizza() {
                return pizza_;
        }
 
        virtual void buildDough() = 0;
        virtual void buildSauce() = 0;
        virtual void buildTopping() = 0;
 
protected:
        Pizza pizza_;
};
 
class HawaiianPizzaBuilder : public PizzaBuilder {
public:
        void buildDough() {
                pizza_.dough("cross");
        }
 
        void buildSauce() {
                pizza_.sauce("mild");
        }
 
        void buildTopping() {
                pizza_.topping("ham+pineapple");
        }
};
 
class SpicyPizzaBuilder : public PizzaBuilder {
public:
        void buildDough() {
                pizza_.dough("pan baked");
        }
 
        void buildSauce() {
                pizza_.sauce("hot");
        }
 
        void buildTopping() {
                pizza_.topping("pepperoni+salami");
        }
};
 
class Cook {
public:
        Cook()
                : pizzaBuilder_(NULL/*nullptr*/)//Chinmay Mandal : nullptr replaced with NULL.
        {       }
 
        ~Cook() {
                if (pizzaBuilder_)
                        delete pizzaBuilder_;
        }
 
        void pizzaBuilder(PizzaBuilder* pizzaBuilder) {
                if (pizzaBuilder_)
                        delete pizzaBuilder_;
 
                pizzaBuilder_ = pizzaBuilder;
        }
 
        const Pizza& getPizza() {
                return pizzaBuilder_->pizza();
        }
 
        void constructPizza() {
                pizzaBuilder_->buildDough();
                pizzaBuilder_->buildSauce();
                pizzaBuilder_->buildTopping();
        }
 
private:
        PizzaBuilder* pizzaBuilder_;
};
 
int main() {
        Cook cook;
        cook.pizzaBuilder(new HawaiianPizzaBuilder);
        cook.constructPizza();
 
        Pizza hawaiian = cook.getPizza();
        hawaiian.open();
 
        cook.pizzaBuilder(new SpicyPizzaBuilder);
        cook.constructPizza();
 
        Pizza spicy = cook.getPizza();
        spicy.open();
}

PHP [edit]

<?php
/** "Product" */
class Pizza {
 
    protected $dough;
    protected $sauce;
    protected $topping;
 
    public function setDough($dough) {
        $this->dough = $dough;
    }
 
    public function setSauce($sauce) {
        $this->sauce = $sauce;
    }
 
    public function setTopping($topping) {
        $this->topping = $topping;
    }
 
    public function showIngredients() {
        echo "Dough   : ".$this->dough."<br/>";
        echo "Sauce   : ".$this->sauce."<br/>";
        echo "Topping : ".$this->topping."<br/>";
    }
}
 
/** "Abstract Builder" */
abstract class PizzaBuilder {
 
    protected $pizza;
 
    public function getPizza() {
        return $this->pizza;
    }
 
    public function createNewPizzaProduct() {
        $this->pizza = new Pizza();
    }
 
    public abstract function buildDough();
    public abstract function buildSauce();
    public abstract function buildTopping();
}
 
/** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
    public function buildDough() {
        $this->pizza->setDough("cross");
    }
 
    public function buildSauce() {
        $this->pizza->setSauce("mild");
    }
 
    public function buildTopping() {
        $this->pizza->setTopping("ham + pineapple");
    }
}
 
/** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {
 
    public function buildDough() {
        $this->pizza->setDough("pan baked");
    }
 
    public function buildSauce() {
        $this->pizza->setSauce("hot");
    }
 
    public function buildTopping() {
        $this->pizza->setTopping("pepperoni + salami");
    }
}
 
/** "Director" */
class Waiter {
 
    protected $pizzaBuilder;
 
    public function setPizzaBuilder(PizzaBuilder $pizzaBuilder) {
        $this->pizzaBuilder = $pizzaBuilder;
    }
 
    public function getPizza() {
        return $this->pizzaBuilder->getPizza();
    }
 
    public function constructPizza() {
        $this->pizzaBuilder->createNewPizzaProduct();
        $this->pizzaBuilder->buildDough();
        $this->pizzaBuilder->buildSauce();
        $this->pizzaBuilder->buildTopping();
    }
}
 
class Tester {
 
    public static function main() {
 
        $oWaiter               = new Waiter();
        $oHawaiianPizzaBuilder = new HawaiianPizzaBuilder();
        $oSpicyPizzaBuilder    = new SpicyPizzaBuilder();
 
        $oWaiter->setPizzaBuilder($oHawaiianPizzaBuilder);
        $oWaiter->constructPizza();
 
        $pizza = $oWaiter->getPizza();
        $pizza->showIngredients();
 
        echo "<br/>";
 
        $oWaiter->setPizzaBuilder($oSpicyPizzaBuilder);
        $oWaiter->constructPizza();
 
        $pizza = $oWaiter->getPizza();
        $pizza->showIngredients();
    }
}
 
Tester::main();

output :

   Dough : cross
   Sauce : mild
   Topping : ham + pineapple
   Dough : pan baked
   Sauce : hot
   Topping : pepperoni + salami

Ruby [edit]

# Product
class Pizza
  attr_accessor :dough, :sauce, :topping
end
 
# Abstract Builder
class PizzaBuilder
  def get_pizza
    @pizza
  end
 
  def create_new_pizza_product
    @pizza = Pizza.new
  end
 
  def build_dough; end
  def build_sauce; end
  def build_topping; end
 
end
 
# ConcreteBuilder
class HawaiianPizzaBuilder < PizzaBuilder
  def build_dough
    @pizza.dough = 'cross'
  end
 
  def build_sauce
    @pizza.sauce = 'mild'
  end
 
  def build_topping
    @pizza.topping = 'ham+pineapple'
  end
end
 
# ConcreteBuilder
class SpicyPizzaBuilder < PizzaBuilder
  def build_dough
    @pizza.dough = 'pan baked'
  end
 
  def build_sauce
    @pizza.sauce = 'hot'
  end
 
  def build_topping
    @pizza.topping = 'pepperoni+salami'
  end
end
 
# Director
class Waiter
  attr_accessor :pizza_builder
 
  def get_pizza
    pizza_builder.get_pizza
  end
 
  def construct_pizza
    pizza_builder.create_new_pizza_product
    pizza_builder.build_dough
    pizza_builder.build_sauce
    pizza_builder.build_topping
  end
end
 
# A customer ordering a pizza.
class BuilderExample
  def main(args = [])
    waiter = Waiter.new
    hawaiian_pizza_builder = HawaiianPizzaBuilder.new
    spicy_pizza_builder = SpicyPizzaBuilder.new
 
    waiter.pizza_builder = hawaiian_pizza_builder
    waiter.construct_pizza
 
    pizza = waiter.get_pizza
  end
end
 
puts BuilderExample.new.main.inspect

References [edit]

  1. ^ Gang Of Four

External links [edit]