Builder

Gamma et al. 95

Intent

Separate the construction of a complex object from its representation so that the same construction process can create different representations.
Design Patterns
— Gamma et al. 95

Motivation Example

A Rich Text Format (RTF) converter (ET++)
  • Converts RTF to many text formats: ASCII, LaTeX, etc.

  • Problem: the number of possible conversions is open-ended

  • The solution should allow adding new converters without modifying the reader

Motivation Example

Solution
  • Design a TextConverter that converts RTF to another representation

  • The RTFReader reads the document and delegates the conversion to the TextConverter

Diagram

Motivation Example

  • TextConverter subclasses specialize in different conversions and formats.

  • They may ignore some requests

    • An ASCIIConverter ignores requests to convert anything except plain text.

  • The Converters are separated from the Reader,
    which is responsible for parsing an RTF document.

Motivation Example

Diagram

Motivation Example

The Builder Pattern
  • Converter classes are called Builder

  • The Reader class is called Director

  • This pattern separates the algorithm for interpreting a textual format from
    how a converted format gets created and represented

Applicability

Use the Builder pattern when
  • The algorithm for creating a complex object should be independent of the parts that make up the object and how they are assembled.

  • The construction process must allow different representations for the object that is constructed.

Structure

UML Collaboration Diagram
Figure 1. UML Collaboration Diagram

Participants (1/2)

Director

The algorithm to construct the product by calling operations of creation and assembly

Builder

Defines the operations for build parts and assembling them

Participants (2/2)

ConcreteBuilder

Constructs and assembles parts of the product by implementing the Builder interface

  • defines and keeps track of the representation it creates

  • provides an operation for retrieving the product

Product

The complex object under construction (ASCIIText, LatexText, TextWidget)

Collaborations

UML Sequence Diagram
Figure 2. UML Sequence Diagram

Consequences

The Builder patter
  • lets you vary a product’s internal representation

  • isolates code for construction and representation

  • gives you finer control over the construction process

Implementation Trade-offs

  1. Assembly and construction interface

    • Builders construct their products in step-by-step fashion

    • The Builder class interface must be general enough to allow the construction of products for all kinds of concrete builders

  2. Why no abstract class for products?

  3. Empty methods as default in Builder

Code Example: The Maze

The MazeBuilder Class (The Builder)
public class MazeBuilder {
    protected MazeBuilder() {}

    public void buildMaze() { }

    public void buildRoom(int room) { }

    public void buildDoor(int roomFrom, int roomTo) { }

    public Maze getMaze() {
        return null;
    }
}

Code Example

The MazeGame Class (The Director)
public class MazeGame {

    public Maze createMaze(MazeBuilder builder) {
        builder.buildMaze();

        builder.buildRoom(1);
        builder.buildRoom(2);
        builder.buildDoor(1, 2);

        return builder.getMaze();
    }

}

Code Example

The Maze Class (The product)
public class Maze {
    public Room roomNo(int n) {
        return null;
    }

    public void addRoom(Room room) {
    }
}

Code Example

The StandardMazeBuilder Class (A Concrete Builder)
public class StandardMazeBuilder extends MazeBuilder {
    private Maze currentMaze;

    @Override
    public void buildMaze() {
        this.currentMaze = new Maze();
    }

    @Override
    public void buildDoor(int n1, int n2) {
        Room r1 = currentMaze.roomNo(n1);
        Room r2 = currentMaze.roomNo(n2);
        Door d = new Door(r1, r2);

        r1.setSide(commonWall(r1, r2), d);
        r2.setSide(commonWall(r2, r1), d);
    }

    @Override
    public Maze getMaze() {
        return currentMaze;
    }

    private Wall commonWall(Room room1, Room room2) {
        return new Wall(room1, room2);
    }

    @Override
    public void buildRoom(int n) {
        if (currentMaze.roomNo(n) == null) {
            Room room = new Room(n);
            currentMaze.addRoom(room);

            room.setSide(Direction.NORTH, new Wall());
            room.setSide(Direction.SOUTH, new Wall());
            room.setSide(Direction.EAST, new Wall());
            room.setSide(Direction.WEST, new Wall());
        }
    }
}

Useful links

Author and Date

  • Design Patterns: Elements of Reusable Object-Oriented Software.
    Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides.
    Addison Wesley. October 1994.