Builder Pattern

Nilesh Parab
5 minute Written by Nilesh Parab on
Builder Pattern Photo by Marcel Strauß on Unsplash

:confused: But why?

Imagine the headache constructing complex objects from constructor that has more than 5 arguments.

Then you need to remember what is what & you explicitly need to send null for any property that you do not want to set.

Take for example below snippet:

// The complex entity
public class IceCream {

    private int scoops;
	private Type type;
	private Flavour flavour;
	private Brand brand;
	private float price;

    // a big exhaustive constructor
    public IceCream(int scoops, Type type, 
                        Flavour flavour, Brand brand, float price) {
        // the usual code here
    }
}

// Using the above complex entity
public class IceCreamMachine {
    public IceCream orderAnIceCream() {
        return new IceCream(1, CUP, MANGO, BASKINS, 125);
    }
}

:building_construction: Builder Pattern

Builder Pattern addresses this problem statement by following a step-by-step approach. Essentially it creates the entire object from small steps.

This comes handy when we have a complex object & a constructor does not help with being informative.

:scroll: How its done?

The implementation is simple. We just create a separate class that provides steps (methods) to set individual properties with ease. Finally it will return the desired object.

  • Create your entity as normal but for the constructor make it private & let it accept a single argument as builder
    public class IceCream {
    
      private int scoops;
      private Type type;
      private Flavour flavour;
      private Brand brand;
      private float price;
    
      public IceCream(Builder builder) {
          this.scoops = builder.scoops;
          this.type = builder.type;
          this.flavour = builder.flavour;
          this.brand = builder.brand;
          this.price = builder.price;
      }
    }
    
  • Create a static inner class as builder
  • The builder is required to have same properties as your entity
  • The builder then also provide methods for setting each property & return itself
  • Below is a snippet for builder
    public class IceCream {
      // leaving out the fields just for now
      public static class Builder {
          // same properties as IceCream entity
          private int scoops;
          private Type type;
          private Flavour flavour;
          private Brand brand;
          private float price;
    
          // keeping a default constructor if we need 
          // to set all properties one by one
          private Builder() {
              super();
          }
    
          // parameterized constructor to create 
          // builder with bare-minimum properties
          private Builder(Flavour flavour, Brand brand) {
              this.brand = brand;
              this.flavour = flavour;
          }
    
          public Builder addScoops(int scoops) {
              this.scoops = this.scoops + scoops;
              return this;
          }
    
          public Builder selectType(Type type) {
              this.type = type;
              return this;
          }
    
          public Builder selectFlavour(Flavour flavour) {
              this.flavour = flavour;
              return this;
          }
    
          public Builder selectBrand(Brand brand) {
              this.brand = brand;
              return this;
          }
    
          public Builder calculatePrice() {
              this.price = (this.brand.getRate() 
                              + this.type.getRate() 
                              + this.flavour.getRate()) * this.scoops;
              return this;
          }
    
          // method invokes the parent class constructor
          public IceCream build() {
              return new IceCream(this);
          }
    
          // static method for easy object creation
          public static Builder createInstance(Flavour flavour, Brand brand) {
              return new Builder(flavour, brand);
          }
    
          // static method for easy object creation
          public static Builder createInstance() {
              return new Builder();
          }
      }
    }
    
  • Below snippet shows how to construct objects using this builder
    // using builder with parameters
    IceCream vanillaSmall = Builder.createInstance(Flavour.VANILLA, 
                                          Brand.BASKINS)
                                      .addScoops(1)
                                      .selectType(Type.CUP)
                                      .calculatePrice()
                                      .build();
    // using builder with all steps explicitly defined
    IceCream mangoLarge = Builder.createInstance()
                              .selectFlavour(Flavour.MANGO)
                              .selectBrand(Brand.KWALITY)
                              .addScoops(3)
                              .selectType(Type.CUP)
                              .calculatePrice()
                              .build();
    
  • The way we now initialize objects is very clean & readable.

:warning: Caveats?

Yes like everything else, we need to maintain the builder with same properties which is cumbersome.

Nilesh Parab
About Nilesh Parab I love building things using Java & JavaScript. Professionally I am more focussed in eCommerce. Music. Motorcycling.