Builder Pattern

  • GoF: Separate the construction of a complex object from its representation so that the same construction process can create different representations.
  • Wiki: The builder pattern is a design pattern designed to provide a flexible solution to various object creation problems in object-oriented programming. The intent of the Builder design pattern is to separate the construction of a complex object from its representation
  • Other: This a pattern people often use but rarely create of there own. This pattern deals with construction of Objects with lot of parameters and want to make the object once we are done constructing it.

Concepts

  • Handles complex constructors
  • Large number of parameters
  • Immutability
  • Examples:
    • StringBuilder
    • DocumentBuilder
    • Locale.Builder

Design considerations

  • Flexibility over telescoping constructors
  • Generally implemented with static inner class
  • Calls appropriate constructor
  • Negates the need for exposed setters
  • Java 1.5+ can take advantage of generics ***

Example/Demo

  • Demonstrate exposed setters (LunchOrderBean.java / LunchOrderBeanDemo.java)
  • Demonstrate Telescoping constructors (LunchOrderTelescopic.java / LunchOrderTelescopicDemo.java)
  • Create Builder (LunchOrder.java / LunchOrderDemo.java)
  • Build out example

Steps to create:

  • Create a class which is supposed to have many fields and required immutable instance
  • Decalre all fields as final, so that they can only be initialized in constructor
  • Create a public static builder inner class
  • Copy all the field declarations in the inner class without making them final (In case you make field inside inner class as final you have to initialize that in constructor else you will ahve compilation error)
  • Create a public default constructor in Builder class (you can put any parameters here to make them mandatory)
  • Now, create methods taking field type as input and returning complete instance after setting that. for example
    public Builder bread(String bread) {
    this.bread = bread;
    return this;
    }
  • Create a private constructor in Outer class that takes this Builder class and sets all the fields from the builder instance.
    private LunchOrder(Builder builder) {
    this.bread = builder.bread;
    this.condiments = builder.condiments;
    this.dressing = builder.dressing;
    this.meat = builder.meat;
    }
  • Create a build method that will return the instance of Outer class. This is achieved by passing this builder instance to the outer class constructor
    public LunchOrder build() {
    return new LunchOrder(this);
    }
  • You can test the above builder as:
    LunchOrder.Builder builder = new LunchOrder.Builder();
    builder.bread("bread").condiments("condiments").dressing("dressing").meat("meat");
    LunchOrder lunchOrder = builder.build();
  • Done

Drawbacks

  • Immutable objects are created
  • Inner static class is generally used for implementation
  • It is always Designed first
  • Adds complexity, as people are not comfortable with object returning itself with each subsequent call

Contrast to other patterns

BuilderPrototype
Handles complex constructorsImplemented around a clone
No interface requiredAvoids calling complex constructors
Can be a saperate classNA
Works with a legacy codeDifficult to implement in legacy code

Summary

  • Creative way to deal with complexity
  • Easy to implement
  • few drawbacks
  • can refactor in with a saperate class (typically implemented with a static inner class)

Next

Explore the Generics version of builder pattern