Builder

Problem

An application needs to create the elements of a complex aggregate. The choice and ordering of elements for building an object needs flexibility to create multiple versions by using same elements. The concrete elements are encapsulated from the client.

Client Code - 1 Client Code -2

addStart addStart

addDesign addImeplement

addImplement addTest

addTest addTest

addStop addStop

Intent

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

Applicability

- the algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled.

- the construction process mush allow different representations for the object that's constructed.

Structure

Participants

- Builder

specifies an abstract interface for creating parts of a Product object.

- ConcreteBuilder

constructs and assembles parts of the product by implementing the Builder interface.

defines and keeps tract of the repessentation it creates.

provides an interface for retrieving the product.

- MyClass

declares an interface of a Product object visible to client.

- ConcreteMyClass

represents the complex object under construction.

defines the elements of object.

builds the product for client specified elements.

Thumb Rules

- It lets you vary a product's internal representation.

- It isolates code for construction and representation.

- It gives finer control over the construction process by step by step construction of product.

- Sometimes creational patterns are complementory: It can use one of the other patterns to implement which components get built. It can use Singleton in their implementations.

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

Example

The Builder pattern separates the construction of a complex object from its representation so that the same construction process can create different representations. This pattern is used by fast food restaurants to construct children’s meals. Children’s meals typically consist of a main item, a side item, a drink, and a toy (e.g., a hamburger, fries, Coke, and toy dinosaur). Note that there can be variation in the content of the children’s meal, but the construction process is the same. Whether a customer orders a hamburger, cheeseburger, or chicken, the process is the same. The employee at the counter directs the crew to assemble a main item, side item, and toy. These items are then placed in a bag. The drink is placed in a cup and remains outside of the bag. This same process is used at competing restaurants.

Code - Before

The client creates MyClassA object without any control over the ordering and choice of its elements.

class MyClass

{

public:

virtual void build() = 0;

}

class MyClassA : public MyClass

{

public:

MyClassA()

{}

virtual void build()

{

start();

design();

implement();

test();

stop();

}

protected:

void start()

{

System.out.println("Starting....");

}

void design()

{

System.out.println("Designing....");

}

void implement()

{

System.out.println("Implement....");

}

void test()

{

System.out.println("Testing....");

}

void stop()

{

System.out.println("Stopping....");

}

}

int main()

{

MyClass *myclass = new MyClassA();

myclass->build();

}

Starting....

Designing....

Imlementing....

Testing....

Stoping....

Code - After

The client creates MyClassA object with his choice of elements.

class MyClassBuilder

{

public:

virtual void addStart() = 0;

virtual void addDesign() = 0;

virtual void addImplement() = 0;

virtual void addTest() = 0;

virtual void addStop() = 0;

MyClass &getMyClass() = 0;

};

class MyClass

{

public:

virtual void build() = 0;

}

class MyClassA : public MyClass

{

private:

vector<int> m_elements

public:

MyClassA()

{}

virtual void build()

{

for(size_t count = 0; count < m_elements.size(); count++)

{

switch(m_elements[count])

{

case 1:

start();

break;

case 2:

design();

break;

case 3:

implement();

break;

case 4:

test();

break;

case 5:

stop();

break;

default:

break;

}

}

}

public void start()

{

System.out.println("Starting....");

}

public void design()

{

System.out.println("Designing....");

}

public void implement()

{

System.out.println("Implement....");

}

public void test()

{

System.out.println("Testing....");

}

public void stop()

{

System.out.println("Stopping....");

}

void loadElements(vector<int> &elements)

{

m_elements = elements;

}

}

class MyClassBuilderA : public MyClassBuilder

{

private:

MyClassA m_myClassA;

vector<int> m_elements;

public:

void addStart()

{

m_elements.push_back(1);

}

void addDesign()

{

m_elements.push_back(2);

}

void addImplement()

{

m_elements.push_back(3);

}

void addTest()

{

m_elements.push_back(4);

}

void addStop()

{

m_elements.push_back(5);

}

MyClass &getMyClass()

{

m_myClassA.loadElements(m_elements);

return m_myClassA;

}

};

int main()

{

MyClassBuilderA myClassBuilderA;

//Construct an object

myClassBuilderA.addStart();

myClassBuilderA.addImplement();

myClassBuilderA.addTest();

myClassBuilderA.addTest();

myClassBuilderA.addStop();

MyClass &myClass = myClassBuilderA.getMyClass();

myClass.build();

}

Starting....

Imlementing....

Testing....

Testing....

Stoping....