Builder is a cre­ation­al design pat­tern that lets you con­struct com­plex objects step by step. The pat­tern allows you to pro­duce dif­fer­ent types and rep­re­sen­ta­tions of an object using the same con­struc­tion code.

Problem: An application needs to create the elements of a complex aggregate. The specification for the aggregate exists on secondary storage and one of many representations needs to be built in primary storage.

If most of the parameters are unused, this makes constructor calls pretty ugly

If most of the parameters are unused, this makes constructor calls pretty ugly

In most cases most of the para­me­ters will be unused, mak­ing the con­struc­tor calls pret­ty ugly. For instance, only a frac­tion of hous­es have swim­ming pools, so the para­me­ters relat­ed to swim­ming pools will be use­less nine times out of ten.

Solution: Separate the construction of a complex object from its representation so that the same construction process can create different representations. Parse a complex representation, create one of several targets

The Builder pat­tern lets you con­struct com­plex objects step by step. The Builder doesn’t allow other objects to access the prod­uct while it’s being built.

The Builder pat­tern lets you con­struct com­plex objects step by step. The Builder doesn’t allow other objects to access the prod­uct while it’s being built.

image.png

<aside>

Applicability

Structure

image.png

  1. The Builder inter­face declares prod­uct con­struc­tion steps that are com­mon to all types of builders.
  2. Con­crete Builders pro­vide dif­fer­ent imple­men­ta­tions of the con­struc­tion steps. Con­crete builders may pro­duce prod­ucts that don’t fol­low the com­mon interface.
  3. Prod­ucts are result­ing objects con­struct­ed by dif­fer­ent builders don’t have to belong to the same class hier­ar­chy or interface.
  4. The Direc­tor class defines the order in which to call con­struc­tion steps, so you can cre­ate and reuse spe­cif­ic con­fig­u­ra­tions of products.
  5. The Client must as­so­ciate one of the builder objects with the direc­tor. Usu­al­ly, it’s done just once, via para­me­ters of the direc­tor’s con­struc­tor. Then the direc­tor uses that builder object for all fur­ther con­struc­tion. How­ev­er, there’s an alter­na­tive approach for when the client pass­es the builder object to the pro­duc­tion method of the direc­tor. In this case, you can use a dif­fer­ent builder each time you pro­duce some­thing with the director.

Checklist:

  1. Decide if a common input and many possible representations (or outputs) is the problem at hand
  2. Encapsulate the parsing of the common input in a director class.
  3. Design a standard protocol for creating all possible output representations: capture the steps of this protocol in a builder interface
  4. Define a builder derived class for each target representation
  5. The client creates a director object and a builder object, and registers the latter with the former
  6. The client asks the director to construct
  7. The client asks the builder to return the result

<aside>

How to Implement

  1. Make sure that you can clear­ly define the com­mon con­struc­tion steps for build­ing all avail­able prod­uct rep­re­sen­ta­tions. Oth­er­wise, you won’t be able to pro­ceed with imple­ment­ing the pattern.
  2. Declare these steps in the base builder interface.
  3. Cre­ate a con­crete builder class for each of the prod­uct rep­re­sen­ta­tions and imple­ment their con­struc­tion steps. Don’t for­get about imple­ment­ing a method for fetch­ing the result of the con­struc­tion. The rea­son why this method can’t be declared inside the builder inter­face is that var­i­ous builders may con­struct prod­ucts that don’t have a com­mon inter­face. There­fore, you don’t know what would be the return type for such a method. How­ev­er, if you’re deal­ing with prod­ucts from a sin­gle hier­ar­chy, the fetch­ing method can be safe­ly added to the base interface.
  4. Think about cre­at­ing a direc­tor class. It may encap­su­late var­i­ous ways to con­struct a prod­uct using the same builder object.
  5. The client code cre­ates both the builder and the direc­tor objects. Before con­struc­tion starts, the client must pass a builder object to the direc­tor. Usu­al­ly, the client does this only once, via para­me­ters of the direc­tor’s con­struc­tor. The direc­tor uses the builder object in all fur­ther con­struc­tion. There’s an alter­na­tive approach, where the builder is passed direct­ly to the con­struc­tion method of the director.
  6. The con­struc­tion result can be obtained direct­ly from the direc­tor only if all prod­ucts fol­low the same inter­face. Oth­er­wise, the client should fetch the result from the builder. </aside>

Pseudocode

image.png

// Using the Builder pattern makes sense only when your products
// are quite complex and require extensive configuration. The
// following two products are related, although they don't have
// a common interface.
class Car is
  // A car can have a GPS, trip computer and some number of
  // seats. Different models of cars (sports car, SUV,
  // cabriolet) might have different features installed or
  // enabled.

class Manual is
  // Each car should have a user manual that corresponds to
  // the car's configuration and describes all its features.

// The builder interface specifies methods for creating the
// different parts of the product objects.
interface Builder is
  method reset()
  method setSeats(...)
  method setEngine(...)
  method setTripComputer(...)
  method setGPS(...)

// The concrete builder classes follow the builder interface and
// provide specific implementations of the building steps. Your
// program may have several variations of builders, each
// implemented differently.
class CarBuilder implements Builder is
  private field car:Car

// A fresh builder instance should contain a blank product
// object which it uses in further assembly.
  constructor CarBuilder() is
    this.reset()

  // The reset method clears the object being built.
  method reset() is
    this.car = new Car()

  // All production steps work with the same product instance.
  method setSeats(...) is
    // Set the number of seats in the car.

  method setEngine(...) is
    // Install a given engine.

  method setTripComputer(...) is
    // Install a trip computer.

  method setGPS(...) is
    // Install a global positioning system.

  // Concrete builders are supposed to provide their own
  // methods for retrieving results. That's because various
  // types of builders may create entirely different products
  // that don't all follow the same interface. Therefore such
  // methods can't be declared in the builder interface (at
  // least not in a statically-typed programming language).
  //
  // Usually, after returning the end result to the client, a
  // builder instance is expected to be ready to start
  // producing another product. That's why it's a usual
  // practice to call the reset method at the end of the
  // `getProduct` method body. However, this behavior isn't
  // mandatory, and you can make your builder wait for an
  // explicit reset call from the client code before disposing
  // of the previous result.
  method getProduct():Car is
    product = this.car
    this.reset()
    return product

// Unlike other creational patterns, builder lets you construct
// products that don't follow the common interface.
class CarManualBuilder implements Builder is
  private field manual:Manual

  constructor CarManualBuilder() is
		this.reset()

  method reset() is
    this.manual = new Manual()

  method setSeats(...) is
    // Document car seat features.

  method setEngine(...) is
    // Add engine instructions.

  method setTripComputer(...) is
    // Add trip computer instructions.

  method setGPS(...) is
    // Add GPS instructions.

  method getProduct():Manual is
    // Return the manual and reset the builder.

// The director is only responsible for executing the building
// steps in a particular sequence. It's helpful when producing
// products according to a specific order or configuration.
// Strictly speaking, the director class is optional, since the
// client can control builders directly.

class Director is
  private field builder:Builder

  // The director works with any builder instance that the
  // client code passes to it. This way, the client code may
  // alter the final type of the newly assembled product.
  method setBuilder(builder:Builder)
    this.builder = builder

  // The director can construct several product variations
  // using the same building steps.
  method constructSportsCar(builder: Builder) is
    builder.reset()
    builder.setSeats(2)
    builder.setEngine(new SportEngine())
    builder.setTripComputer(true)
    builder.setGPS(true)

  method constructSUV(builder: Builder) is
    // ...

// The client code creates a builder object, passes it to the
// director and then initiates the construction process. The end
// result is retrieved from the builder object.
class Application is

  method makeCar() is
    director = new Director()

    CarBuilder builder = new CarBuilder()
    director.constructSportsCar(builder)
    Car car = builder.getProduct()

    CarManualBuilder builder = new CarManualBuilder()
    director.constructSportsCar(builder)

    // The final product is often retrieved from a builder
    // object since the director isn't aware of and not
    // dependent on concrete builders and products.
    Manual manual = builder.getProduct()