Builder pattern: Difference between revisions
Appearance
Content deleted Content added
Undid revision 424929047 by 65.91.7.194 (talk) |
|||
Line 278: | Line 278: | ||
==External links== |
==External links== |
||
*The JavaWorld article [http://www.javaworld.com/javaworld/jw-01-2004/jw-0102-toolbox.html Build user interfaces without getters and setters] ([[Allen Holub]]) shows the complete Java source code for a Builder. |
|||
*[http://www.ddj.com/java/208403883?pgno=2 Item 2: Consider a builder] by Joshua Bloch |
|||
{{Design Patterns Patterns}} |
{{Design Patterns Patterns}} |
||
Revision as of 02:36, 20 April 2011
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 structural pattern.
Class diagram
- 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.
- 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.
- Product
- The final object that will be created by the Director using Builder.
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 are built. Abstract Factory, Builder, and Prototype can use Singleton in their implementations.
- Builders are good candidates for a fluent interface.
Example
An example in 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 hawaiian = cook.getPizza();
cook.setPizzaBuilder(spicyPizzaBuilder);
cook.constructPizza();
Pizza spicy = cook.getPizza();
}
}
Example in C++
#include <string>
#include <iostream>
using namespace std;
// "Product"
class Pizza
{
public:
void setDough(const string& dough)
{
m_dough = dough;
}
void setSauce(const string& sauce)
{
m_sauce = sauce;
}
void setTopping(const string& topping)
{
m_topping = topping;
}
void open() const
{
cout << "Pizza with " << m_dough << " dough, " << m_sauce << " sauce and "
<< m_topping << " topping. Mmm." << endl;
}
private:
string m_dough;
string m_sauce;
string m_topping;
};
// "Abstract Builder"
class PizzaBuilder
{
public:
Pizza* getPizza()
{
return m_pizza;
}
void createNewPizzaProduct()
{
m_pizza = new Pizza;
}
virtual void buildDough() = 0;
virtual void buildSauce() = 0;
virtual void buildTopping() = 0;
protected:
Pizza* m_pizza;
};
//----------------------------------------------------------------
class HawaiianPizzaBuilder : public PizzaBuilder
{
public:
virtual void buildDough()
{
m_pizza->setDough("cross");
}
virtual void buildSauce()
{
m_pizza->setSauce("mild");
}
virtual void buildTopping()
{
m_pizza->setTopping("ham+pineapple");
}
};
class SpicyPizzaBuilder : public PizzaBuilder
{
public:
virtual void buildDough()
{
m_pizza->setDough("pan baked");
}
virtual void buildSauce()
{
m_pizza->setSauce("hot");
}
virtual void buildTopping()
{
m_pizza->setTopping("pepperoni+salami");
}
};
//----------------------------------------------------------------
class Cook
{
public:
void setPizzaBuilder(PizzaBuilder* pb)
{
m_pizzaBuilder = pb;
}
Pizza* getPizza()
{
return m_pizzaBuilder->getPizza();
}
void constructPizza()
{
m_pizzaBuilder->createNewPizzaProduct();
m_pizzaBuilder->buildDough();
m_pizzaBuilder->buildSauce();
m_pizzaBuilder->buildTopping();
}
private:
PizzaBuilder* m_pizzaBuilder;
};
int main()
{
Cook cook;
PizzaBuilder* hawaiianPizzaBuilder = new HawaiianPizzaBuilder;
PizzaBuilder* spicyPizzaBuilder = new SpicyPizzaBuilder;
cook.setPizzaBuilder(hawaiianPizzaBuilder);
cook.constructPizza();
Pizza* hawaiian = cook.getPizza();
hawaiian->open();
cook.setPizzaBuilder(spicyPizzaBuilder);
cook.constructPizza();
Pizza* spicy = cook.getPizza();
spicy->open();
delete hawaiianPizzaBuilder;
delete spicyPizzaBuilder;
delete hawaiian;
delete spicy;
}
External links
- The JavaWorld article Build user interfaces without getters and setters (Allen Holub) shows the complete Java source code for a Builder.
- Item 2: Consider a builder by Joshua Bloch