Builder Design Pattern

FrugalisMinds

Author - FrugalisMinds

What is Builder Design Pattern ? Why we should care about it ?

Starting from Creational Design Pattern, so wikipedia says “creational design pattern are design pattern that deals with object creation mechanism, trying to create objects in manner that is suitable to the situation”.

The basic form of object creations could result in design problems and result in complex design problems, so to overcome this problem Creational Design Pattern somehow allows you to create the object.

Builder is one of the Creational Design Pattern.

When to consider the Builder Design Pattern ?

Builder is useful when you need to do lot of things to build an Object. Let’s imagine DOM (Document Object Model), so if we need to create the DOM.

We could have to do lot of things, appending plenty of nodes and attaching attributes to them. We could also imagine about the huge XML Object creation where we will have to do lot of work to create the Object.

A Factory is used basically when we could create the entire object in one shot.

As Joshua Bloch (He led the Design of the many library Java Collections Framework and many more) - “Builder Pattern is good choice when designing the class whose constructor or static factories would have more than handful of parameters

While considering the pattern you need to look whether Object is having Following

1. Complex Constructor :-

Multiple constructor having multiple parameters with nested Object. Let’s say you love Pizza (PS : I Love Burger ) . We might have encountered time in where we need customise Object(pizza).

MyPizza(int size) { ... }
MyPizza(int size, boolean cheese) { ... }
MyPizza(int size, boolean cheese, boolean pepperoni) { ... }
MyPizza(int size, boolean cheese, boolean pepperoni, boolean bacon) { ... }
MyPizza(int size, boolean cheese, boolean pepperoni, boolean bacon, boolean veggisAllowed) { ... }
view raw PizzaHotchPotch hosted with ❤ by GitHub

This is called Telescoping Constructor Pattern and problem with this is once constructor have more than 4-5 arguments it is hard to remember the order of parameters. (Although some IDE solves this problems)

One alternative to this problem is we could use JAVABean Pattern where you call constructor with required argument and use setter afterwards -

MyPizza mypizza = new MyPizza(12);
mypizza.setCheese(true);
mypizza.setPepperoni(true);
mypizza.setBacon(true);
view raw PizzabySetter hosted with ❤ by GitHub

The Problem is with that Object is created on several calls, it may be in inconsistent state partway through its construction.

2. Large Number of Parameter - Having large number of parameters is also key point to consider.

3. Immutability - You could force the immutability to the object once it is done.

Let’s see any example and learn how to implement the builder pattern :

import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
Public class MyPizza{
private int size;
private boolean cheese;
private boolean pepperoni;
private boolean bacon;
public void MyPizza(){
}
public void MyPizza(int size, boolean cheese, boolean pepperoni, boolean bacon){
this.size = size;
this.cheese = cheese;
this.pepperoni = pepperoni;
this.bacon = bacon;
}
//Setter And Getter already defined through lombok.Getter and lombok.setter
}
view raw Pizza hosted with ❤ by GitHub

Things are simple when we have 4-5 parameters but eventually becomes messy when we have more than this.

Convert to Builder Pattern : Let’s now add extra fields to the to the POJO and convert it into Builder Design. Create the static anonymous inner class name Builder to the POJO, why static because we want to return or use the current object. Add same fields of POJO and setter of each field with return type of Builder Class. Lastly add the build() method which will return the Object of our POJO.

Public class MyPizza{
private int size;
private boolean cheese;
private boolean pepperoni;
private boolean bacon;
private boolean veggies;
private boolean blackPepper;
public MyPizza(int size,boolean cheese, boolean pepperoni, boolean bacon, boolean veggies, boolean blackPepper){
this.size = size;
this.cheese = cheese;
this.pepperoni = pepperoni;
this.bacon = bacon;
this.veggies = veggies;
this.blackPepper = blackPepper;
}
//No Setter to Impose Immutibility Of the Object
public int getSize(){
return size;
}
public boolean isPepperoni(){
return pepperoni;
}
public boolean isBacon(){
return bacon;
}
public boolean isVeggies(){
return veggies;
}
static class Builder{
private int size;
private boolean cheese;
private boolean pepperoni;
private boolean bacon;
private boolean veggies;
private boolean blackPepper;
public Builder setSize(int size){
this.size = size;
return this;
}
public Builder setPepperoni(boolean pepperoni){
this.pepperoni = pepperoni;
return this;
}
public Builder setBacon(boolean bacon){
this.bacon = bacon;
return this;
}
public Builder setVeggies(boolean veggies){
this.veggies = veggies;
return this;
}
public Builder setBlackPepper(boolean blackPepper){
this.blackPepper = blackPepper;
return this;
}
public MyPizza build(){
return new MyPizza(size,cheese,pepperoni,bacon,veggies,blackPepper);
//See No need to remember the order of arguments in constructor, while coding you only needs to remember
}
}
}
view raw PizzaBuilder hosted with ❤ by GitHub

The resulting builder create code:

MyPizza myPizza = new MyPizza.Builder()
.setSize(10)
.setPepperoni(true);
.setBacon(true)
.setVeggies(true)
.setBlackPepper(true)
.build();
view raw MyPizzaBuilder hosted with ❤ by GitHub

Pros :

  1. Code is more readable and maintainable if number of property are more than 4-5 in class.
  2. You can force the Immutability to the Object by not creating the setter() in POJO and only allowing the getter() in POJO.
  3. Robustness to the code as fully constructed object will be available always.

Cons :

  1. It increases the code duplication in the class well it can be improved with library like Project Lombok.

So How was your Pizza, Keep Building, Keep Coding.

Connect with us at LinkedIn -

Written By - Yogesh Joshi