Home | FAQ | Contact me

Builder Pattern

The utility of the Builder Pattern is a clean way to an arbitrary and messy constructor plus enforce immutability of the resulting object. The constructor doesn't have to port enough arguments to support the object's entire configuration, nor choose a subset thereof. And you don't need to shore up what's missing using setters that violate immutability.

The Builder Pattern originated with Joshua Bloch in Effective Java (2nd edition). The GoF (the original "Gang of Four") also have a Builder Pattern, but it's slightly different.

For my preferred example, go to bottom.

First example

Pizza pizza = new Pizza( 12 );
pizza.setCheese( true );
pizza.setPepperoni( true );
pizza.setBacon( true );

Illustration of the Builder pattern:

public class Pizza
{
  private int     size;
  private boolean cheese;
  private boolean pepperoni;
  private boolean bacon;

  public static class Builder
  {
    // required
    private final int size;

    // optional
    private boolean cheese    = false;
    private boolean pepperoni = false;
    private boolean bacon     = false;

    public Builder( int size ) { this.size = size; }

    public Builder cheese( boolean value )    { cheese = value; return this; }
    public Builder pepperoni( boolean value ) { pepperoni = value; return this; }
    public Builder bacon( boolean value )     { bacon = value; return this; }

    public Pizza build()                      { return new Pizza( this ); }
  }

  private Pizza( Builder builder )
  {
    size      = builder.size;
    cheese    = builder.cheese;
    pepperoni = builder.pepperoni;
    bacon     = builder.bacon;
  }
}


Pizza pizza = new Pizza.Builder( 12 )
                       .cheese( true )
                       .pepperoni( true )
                       .bacon( true )
                       .build();

Telescoping anti-pattern:

Pizza( int size ) { ... }
Pizza( int size, boolean cheese ) { ... }
Pizza( int size, boolean cheese, boolean pepperoni ) { ... }
Pizza( int size, boolean cheese, boolean pepperoni, boolean bacon ) { ... }

Wild-setters anti-pattern:

A second example

Person.java:
public class Person
{
   private final String  lastName;
   private final String  firstName;
   private final String  middleName;
   private final String  salutation;
   private final String  suffix;
   private final String  streetAddress;
   private final String  city;
   private final String  state;
   private final boolean isFemale;
   private final boolean isEmployed;
   private final boolean isHomewOwner;

   public Person(
      final String  newLastName,
      final String  newFirstName,
      final String  newMiddleName,
      final String  newSalutation,
      final String  newSuffix,
      final String  newStreetAddress,
      final String  newCity,
      final String  newState,
      final boolean newIsFemale,
      final boolean newIsEmployed,
      final boolean newIsHomeOwner )
   {
      this.lastName      = newLastName;
      this.firstName     = newFirstName;
      this.middleName    = newMiddleName;
      this.salutation    = newSalutation;
      this.suffix        = newSuffix;
      this.streetAddress = newStreetAddress;
      this.city          = newCity;
      this.state         = newState;
      this.isFemale      = newIsFemale;
      this.isEmployed    = newIsEmployed;
      this.isHomewOwner  = newIsHomeOwner;
   }
}
PersonBuilder.java:
public class PersonBuilder
{
   private String  newLastName;
   private String  newFirstName;
   private String  newMiddleName;
   private String  newSalutation;
   private String  newSuffix;
   private String  newStreetAddress;
   private String  newCity;
   private String  newState;
   private boolean newIsFemale;
   private boolean newIsEmployed;
   private boolean newIsHomeOwner;

   public PersonBuilder() { }

   public PersonBuilder setNewLastName( String newLastName )
   {
      this.newLastName = newLastName;
      return this;
   }

   public PersonBuilder setNewFirstName( String newFirstName )
   {
      this.newFirstName = newFirstName;
      return this;
   }

   public PersonBuilder setNewMiddleName( String newMiddleName )
   {
      this.newMiddleName = newMiddleName;
      return this;
   }

   public PersonBuilder setNewSalutation( String newSalutation )
   {
      this.newSalutation = newSalutation;
      return this;
   }

   public PersonBuilder setNewSuffix( String newSuffix )
   {
      this.newSuffix = newSuffix;
      return this;
   }

   public PersonBuilder setNewStreetAddress( String newStreetAddress )
   {
      this.newStreetAddress = newStreetAddress;
      return this;
   }

   public PersonBuilder setNewCity( String newCity )
   {
      this.newCity = newCity;
      return this;
   }

   public PersonBuilder setNewState( String newState )
   {
      this.newState = newState;
      return this;
   }

   public PersonBuilder setNewIsFemale( boolean newIsFemale )
   {
      this.newIsFemale = newIsFemale;
      return this;
   }

   public PersonBuilder setNewIsEmployed( boolean newIsEmployed )
   {
      this.newIsEmployed = newIsEmployed;
      return this;
   }

   public PersonBuilder setNewIsHomeOwner( boolean newIsHomeOwner )
   {
      this.newIsHomeOwner = newIsHomeOwner;
      return this;
   }

   public Person createPerson()
   {
      return new Person( newLastName, newFirstName, newMiddleName, newSalutation, newSuffix,
                         newStreetAddress, newCity, newState, newIsFemale, newIsEmployed,
                         newIsHomeOwner );
   }
}

A third example

Here's a framework for adding a Builder class to any POJO or other useful class. What it does, using name() and description() won't hold for every situation, but are merely examples. I've done this before (above), but not so elegantly and upon seeing a NiFi example of this (class Relationship), I thought I'd make this note.

publc class Whatever
{
  private String name = "";
  private String description = "";

  // whatever's implementation...
  public String  getName()...
  public String  getDescription()...
  public int     compareTo( Whatever object )...
  public boolean equals( Object other )...
  public int     hashCode()...
  public String  toString()...

  public final class Builder
  {
    private String name = "";
    private String description = "";

    public Builder() { }

    public Whatever.Builder name( String name )
    {
      if( name != null )
        this.name = name;
      return this;
    }

    public Whatever.Builder description( String description )
    {
      if( description != null )
        this.description = description;
      return this;
    }

    public Whatever build() { return new Whatever( this ); }
  }
}

The mega example

This is how Apache NiFi implements PropertyDescriptor. It's how I always do the Builder pattern.

class Cake
{
  private final double sugar;
  private final double butter;
  private final int    eggs;
  private final int    vanila;
  private final double flour;
  private final double bakingpowder;
  private final double milk;
  private final int    cherry;

  protected Cake( Builder builder )
  {
    sugar        = builder.sugar;
    butter       = builder.butter;
    eggs         = builder.eggs;
    vanila       = builder.vanila;
    flour        = builder.flour;
    bakingpowder = builder.bakingpowder;
    milk         = builder.milk;
    cherry       = builder.cherry;
  }

  public static class Builder
  {
    private double sugar;
    private double butter;
    private int    eggs;
    private int    vanila;
    private double flour;
    private double bakingpowder;
    private double milk;
    private int    cherry;

    public Builder sugar( double cup )          { this.sugar         = cup;    return this; }
    public Builder butter( double cup )         { this.butter        = cup;    return this; }
    public Builder eggs( int number )           { this.eggs          = number; return this; }
    public Builder vanila( int spoon )          { this.vanila        = spoon;  return this; }
    public Builder flour( double cup )          { this.flour         = cup;    return this; }
    public Builder bakingpowder( double spoon ) { this.backingpowder = spoon;  return this; }
    public Builder milk( double cup )           { this.milk          = cup;    return this; }
    public Builder cherry( int number )         { this.cherry        = number; return this; }
    public Cake build()                         { return new Cake( this ); }
  }
}

Using the above...

public static void main( String args[] )
{
  Cake whiteCake = new Cake.Builder()
                          .sugar( 1 )
                          .butter( 0.5 )
                          .eggs( 2 )
                          .vanila( 2 )
                          .flour( 1.5 )
                          .bakingpowder( 0.75 )
                          .milk( 0.5 )
                          .build();
}