When would you use the Builder Pattern?

256,444

Solution 1

The key difference between a builder and factory IMHO, is that a builder is useful when you need to do lots of things to build an object. For example imagine a DOM. You have to create plenty of nodes and attributes to get your final object. A factory is used when the factory can easily create the entire object within one method call.

One example of using a builder is a building an XML document, I've used this model when building HTML fragments for example I might have a Builder for building a specific type of table and it might have the following methods (parameters are not shown):

BuildOrderHeaderRow()
BuildLineItemSubHeaderRow()
BuildOrderRow()
BuildLineItemSubRow()

This builder would then spit out the HTML for me. This is much easier to read than walking through a large procedural method.

Check out Builder Pattern on Wikipedia.

Solution 2

Below are some reasons arguing for the use of the pattern and example code in Java, but it is an implementation of the Builder Pattern covered by the Gang of Four in Design Patterns. The reasons you would use it in Java are also applicable to other programming languages as well.

As Joshua Bloch states in Effective Java, 2nd Edition:

The builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameters.

We've all at some point encountered a class with a list of constructors where each addition adds a new option parameter:

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

This is called the Telescoping Constructor Pattern. The problem with this pattern is that once constructors are 4 or 5 parameters long it becomes difficult to remember the required order of the parameters as well as what particular constructor you might want in a given situation.

One alternative you have to the Telescoping Constructor Pattern is the JavaBean Pattern where you call a constructor with the mandatory parameters and then call any optional setters after:

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

The problem here is that because the object is created over several calls it may be in an inconsistent state partway through its construction. This also requires a lot of extra effort to ensure thread safety.

The better alternative is to use 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;
  }
}

Note that Pizza is immutable and that parameter values are all in a single location. Because the Builder's setter methods return the Builder object they are able to be chained.

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

This results in code that is easy to write and very easy to read and understand. In this example, the build method could be modified to check parameters after they have been copied from the builder to the Pizza object and throw an IllegalStateException if an invalid parameter value has been supplied. This pattern is flexible and it is easy to add more parameters to it in the future. It is really only useful if you are going to have more than 4 or 5 parameters for a constructor. That said, it might be worthwhile in the first place if you suspect you may be adding more parameters in the future.

I have borrowed heavily on this topic from the book Effective Java, 2nd Edition by Joshua Bloch. To learn more about this pattern and other effective Java practices I highly recommend it.

Solution 3

Consider a restaurant. The creation of "today's meal" is a factory pattern, because you tell the kitchen "get me today's meal" and the kitchen (factory) decides what object to generate, based on hidden criteria.

The builder appears if you order a custom pizza. In this case, the waiter tells the chef (builder) "I need a pizza; add cheese, onions and bacon to it!" Thus, the builder exposes the attributes the generated object should have, but hides how to set them.

Solution 4

For a multi-threaded problem, we needed a complex object to be built up for each thread. The object represented the data being processed, and could change depending on the user input.

Could we use a factory instead? Yes

Why didn't we? Builder makes more sense I guess.

Factories are used for creating different types of objects that are the same basic type (implement the same interface or base class).

Builders build the same type of object over and over, but the construction is dynamic so it can be changed at runtime.

Solution 5

I always disliked the Builder pattern as something unwieldy, obtrusive and very often abused by less experienced programmers. Its a pattern which only makes sense if you need to assemble the object from some data which requires a post-initialisation step (i.e. once all the data is collected - do something with it). Instead, in 99% of the time builders are simply used to initialise the class members.

In such cases it is far better to simply declare withXyz(...) type setters inside the class and make them return a reference to itself.

Consider this:

public class Complex {

    private String first;
    private String second;
    private String third;

    public String getFirst(){
       return first; 
    }

    public void setFirst(String first){
       this.first=first; 
    }

    ... 

    public Complex withFirst(String first){
       this.first=first;
       return this; 
    }

    public Complex withSecond(String second){
       this.second=second;
       return this; 
    }

    public Complex withThird(String third){
       this.third=third;
       return this; 
    }

}


Complex complex = new Complex()
     .withFirst("first value")
     .withSecond("second value")
     .withThird("third value");

Now we have a neat single class that manages its own initialization and does pretty much the same job as the builder, except that its far more elegant.

Share:
256,444
Charles Graham
Author by

Charles Graham

Programmer from Philly.

Updated on July 16, 2022

Comments

  • Charles Graham
    Charles Graham almost 2 years

    What are some common, real world examples of using the Builder Pattern? What does it buy you? Why not just use a Factory Pattern?