Fork me on GitHub

Builder

Motivation

The Builder, as the name suggests, builds complex objects from simple ones, step-by-step.

Let’s say we order a child meal at a fast food restaurant. What is it comprised of? Well, a burger, a cold drink, fries and a toy. In fact, a child meal consist of a main item, a side item, a drink and a toy.

Every time a child meal is ordered, the service boy will take a burger, fries, a cold drink and a toy. Now suppose that there are 3 types of burgers available – Cheese, Beef and Chicken, 2 types of cold drinks available – Cola and Orange, and 2 types of toys available – a car and a doll.

So, the order might be a combination of one of these, but the process of building a child meal will be the same. One burger, one cold drink, fries and one toy. All these items are placed in a paper bag, which is given to the customer. The process of producing a child meal is an example of the Builder pattern.

The Builder pattern separates construction of a complex object from its representation, so that the same construction process can create different representations.

Story

This pattern is used by PC shops to construct PCs. PC is a combination of various parts, such as a CPU, a motherboard, memory, storage, power supply, video card, etc. To build a PC, the same construction process is used, even if we have different variations for each part. Whether a customer picks a classical hard disk or SSD for storage, the construction process is the same.

Image

alt text

The Antec P180, By DonES (Own work) [GFDL or CC-BY-SA-3.0], via Wikimedia Commons

UML

Structure

The Product class represents a complex object.
The Builder specifies an abstract interface for creating parts of a Product object.
The ConcreteBuilder class constructs and assembles parts of the product, implementing the Builder interface.
The Director class constructs an object using the Builder interface.

Implementation

Builder.java

package com.hundredwordsgof.builder;

/**
 * Builder, declares interface for creating parts of a Product object
 * 
 */
abstract class Builder {

  public abstract Builder createProduct();

  public abstract Builder buildPart1(String part);

  public abstract Builder buildPart2(String part);
}

ConcreteBuilder.java

package com.hundredwordsgof.builder;

/**
 * ConcreteBuilder class, constructs and assembles parts of the Product by
 * implementing the Builder interface
 */
public class ConcreteBuilder extends Builder {

  private Product product;

  public Builder createProduct() {
    this.product = new Product();
    return this;
  }

  public Builder buildPart1(String part) {
    product.setPart1(part);
    return this;
  }

  public Builder buildPart2(String part) {
    product.setPart2(part);
    return this;
  }

  public Product getResult() {
    return product;
  }
}

Product.java

package com.hundredwordsgof.builder;

/**
 * Product class, represents complex object
 */
public class Product {

  private String part1;

  private String part2;

  public void setPart1(String part1) {
    this.part1 = part1;
  }

  public void setPart2(String part2) {
    this.part2 = part2;
  }

  public String getPart1() {
    return part1;
  }

  public String getPart2() {
    return part2;
  }
}

Director.java

package com.hundredwordsgof.builder;

/**
 * 
 * Director class, constructs an object using the Builder interface
 *
 */
public class Director {

  private Builder builder;

  public Director(Builder builder) {
    this.builder = builder;
  }

  public void construct() {
    builder.createProduct().buildPart1("part1").buildPart2("part2");
  }
}

Usage

BuilderTest.java

package com.hundredwordsgof.builder;

import static org.junit.Assert.*;
import org.junit.Test;

/**
 * Test implementation of the Builder pattern.
 */
public class BuilderTest {

  @Test
  public void testBuilder() {

    // creates object of type ConcreteBuilder
    ConcreteBuilder builder = new ConcreteBuilder();
    // creates object of type Director
    Director director = new Director(builder);
    // Director constructs a Product
    director.construct();
    // get Product from builder
    Product product = builder.getResult();

    assertEquals(product.getPart1(), "part1");
    assertEquals(product.getPart2(), "part2");
  }
}