Builder Pattern


Let us understand the Builder Pattern

Builder Pattern is mainly used to construct complex objects, which means objects having lot of attributes (some of them are optional).

And it defines same object building process (as the name indicates) to construct any number of complex objects.

In this pattern, construction of complex object is separated from its representation.


Problem with Factory and Abstract factory patterns

Builder pattern was introduced to address the problem with factory and abstract factory patterns when object contains lot of attributes

If we consider Factory or Abstract factory pattern when object contains lot of attributes then we will face below problems

1.We will end up with sending too many arguments to factory class which can become error prone

2.Some parameters are optional sometimes and in factory pattern, it’s required to send all parameters and we have to send NULL values to all optional attributes.

3.Since we are passing many parameters to factory class, object creation process is very complex within factory class.

Problem with constructors and setters

We can use constructors with all the required attributes and then define setter method to set the optional attributes.

When we use this approach, the problem is object state will be inconsistent until all the setters are called to set the attributes explicitly.

In order to create complete object as per the requirement without any of the above problems, we use Builder pattern

Builder pattern solves the above problem by defining a way to build the object step by step and provide a single method that will actually return the final required object.

When to use Builder pattern?

Prefer Builder pattern when we need to create object which has lot of attributes in which some of them are optional and some of them are required attributes.

Let’s understand and implement Builder pattern in practical

Requirement
Create Employee object with attributes FirstName,lastName,age,mobile,address,salary


Case 1:

Assume all attributes are required attributes

In this case, we don’t need to use Builder pattern, we can just define Employee class with one constructor which takes all attributes as parameters

We just need to create object by passing all attributes as all are required.

Below code is sufficient enough to address above case

  1. package com.kb.builder;
  2.  
  3. public class Employee {
  4.     private String firstName;//required
  5.     private String lastName;//required
  6.     private int age;//required
  7.     private long mobile;//required
  8.     private String address;//optional
  9.     private double salary;//optional
  10.  
  11.     public Employee(String firstName, String lastName, int age, long mobile, String address, double salary) {
  12.         this.firstName = firstName;
  13.         this.lastName = lastName;
  14.         this.age = age;
  15.         this.mobile = mobile;
  16.         this.address = address;
  17.         this.salary = salary;
  18.     }
  19. }
package com.kb.builder;

public class Employee {
	private String firstName;//required
	private String lastName;//required
	private int age;//required
	private long mobile;//required
	private String address;//optional
	private double salary;//optional

	public Employee(String firstName, String lastName, int age, long mobile, String address, double salary) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;
		this.mobile = mobile;
		this.address = address;
		this.salary = salary;
	}
}


Case 2:

Assume some attributes like address, salary attributes are optional

In this case, if we don’t use Builder pattern, then we have below 2 options

option 1:


Define multiple constructors

One which takes only required attributes as parameters

One which takes all the required attributes plus the first optional attribute

One which takes all the required attributes plus first and second optional attributes and so on

It looks something like below code

  1. package com.kb.builder;
  2.  
  3. public class Employee {
  4.     private String firstName;
  5.     private String lastName;
  6.     private int age;
  7.     private long mobile;
  8.     private String address;
  9.     private double salary;
  10.  
  11.     public Employee(String firstName, String lastName, int age, long mobile) {
  12.         this.firstName = firstName;
  13.         this.lastName = lastName;
  14.         this.age = age;
  15.         this.mobile = mobile;
  16.     }
  17.    
  18.     public Employee(String firstName, String lastName, int age, long mobile, String address) {
  19.         this.firstName = firstName;
  20.         this.lastName = lastName;
  21.         this.age = age;
  22.         this.mobile = mobile;
  23.         this.address = address;
  24.     }
  25.    
  26.     public Employee(String firstName, String lastName, int age, long mobile, String address, double salary) {
  27.         this.firstName = firstName;
  28.         this.lastName = lastName;
  29.         this.age = age;
  30.         this.mobile = mobile;
  31.         this.address = address;
  32.         this.salary = salary;
  33.     }
  34.  
  35. }
package com.kb.builder;

public class Employee {
	private String firstName;
	private String lastName;
	private int age;
	private long mobile;
	private String address;
	private double salary;

	public Employee(String firstName, String lastName, int age, long mobile) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;
		this.mobile = mobile;
	}
	
	public Employee(String firstName, String lastName, int age, long mobile, String address) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;
		this.mobile = mobile;
		this.address = address;
	}
	
	public Employee(String firstName, String lastName, int age, long mobile, String address, double salary) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.age = age;
		this.mobile = mobile;
		this.address = address;
		this.salary = salary;
	}

}


The above code definitely works but it creates more problem when number of attributes increases in a class.

Number of constructors also increases and leads to lot of confusion and it becomes very difficult to maintain the code

option 2:

Create class with all the attributes and getters and setters for each attribute

  1. package com.kb.builder;
  2. public class Employee {
  3.     private String firstName;
  4.     private String lastName;
  5.     private int age;
  6.     private long mobile;
  7.     private String address;
  8.     private double salary;
  9.     public String getFirstName() {
  10.         return firstName;
  11.     }
  12.     public void setFirstName(String firstName) {
  13.         this.firstName = firstName;
  14.     }
  15.     public String getLastName() {
  16.         return lastName;
  17.     }
  18.     public void setLastName(String lastName) {
  19.         this.lastName = lastName;
  20.     }
  21.     public int getAge() {
  22.         return age;
  23.     }
  24.     public void setAge(int age) {
  25.         this.age = age;
  26.     }
  27.     public long getMobile() {
  28.         return mobile;
  29.     }
  30.     public void setMobile(long mobile) {
  31.         this.mobile = mobile;
  32.     }
  33.     public String getAddress() {
  34.         return address;
  35.     }
  36.     public void setAddress(String address) {
  37.         this.address = address;
  38.     }
  39.     public double getSalary() {
  40.         return salary;
  41.     }
  42.     public void setSalary(double salary) {
  43.         this.salary = salary;
  44.     }
  45. }
package com.kb.builder;
public class Employee {
	private String firstName;
	private String lastName;
	private int age;
	private long mobile;
	private String address;
	private double salary;
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public long getMobile() {
		return mobile;
	}
	public void setMobile(long mobile) {
		this.mobile = mobile;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
}


In this case, we can call setter for whatever the attribute we need to set value.

But the problem here is, Object will be inconsistent until all the setters are invoked for required attributes.

The most feasible solution to solve above problem is Builder pattern

Steps to implement the Builder pattern

1) Create a EmployeeBuilder static nested class and then copy all the attributes from the outer Employee class to the nested EmployeeBuilder class.

2) Builder class should have a public constructor with all the required attributes as parameters.

3) Builder class should have methods to set the optional parameters and it should return the same Builder object after setting the optional attribute.

4) The final step is to provide a build() method in the builder class that will return the Object needed by client program. For this we need to have a private constructor in the Employee Class with EmployeeBuilder class as argument

  1. package com.kb.builder;
  2.  
  3. public class Employee {
  4.     private String firstName;//required
  5.     private String lastName;//required
  6.     private int age;//required
  7.     private long mobile;//required
  8.     private String address;//optional
  9.     private double salary;//optional
  10.  
  11.     private Employee(EmployeeBuilder builder) {
  12.         this.firstName = builder.firstName;
  13.         this.lastName = builder.lastName;
  14.         this.age = builder.age;
  15.         this.mobile = builder.mobile;
  16.         this.address = builder.address;
  17.         this.salary = builder.salary;
  18.  
  19.     }
  20.  
  21.     public String getFirstName() {
  22.         return firstName;
  23.     }
  24.  
  25.     public String getLastName() {
  26.         return lastName;
  27.     }
  28.  
  29.     public int getAge() {
  30.         return age;
  31.     }
  32.  
  33.     public long getMobile() {
  34.         return mobile;
  35.     }
  36.  
  37.     public String getAddress() {
  38.         return address;
  39.     }
  40.  
  41.     public double getSalary() {
  42.         return salary;
  43.     }
  44.  
  45.     public static class EmployeeBuilder {
  46.         private String firstName;
  47.         private String lastName;
  48.         private int age;
  49.         private long mobile;
  50.         private String address;
  51.         private double salary;
  52.  
  53.         public EmployeeBuilder(String firstName, String lastName, int age, long mobile) {
  54.             this.firstName = firstName;
  55.             this.lastName = lastName;
  56.             this.age = age;
  57.             this.mobile = mobile;
  58.         }
  59.  
  60.         public EmployeeBuilder address(String address) {
  61.             this.address = address;
  62.             return this;
  63.         }
  64.  
  65.         public EmployeeBuilder salary(double salary) {
  66.             this.salary = salary;
  67.             return this;
  68.         }
  69.  
  70.         public Employee build() {
  71.             return new Employee(this);
  72.         }
  73.  
  74.     }
  75.  
  76. }
package com.kb.builder;

public class Employee {
	private String firstName;//required
	private String lastName;//required
	private int age;//required
	private long mobile;//required
	private String address;//optional
	private double salary;//optional

	private Employee(EmployeeBuilder builder) {
		this.firstName = builder.firstName;
		this.lastName = builder.lastName;
		this.age = builder.age;
		this.mobile = builder.mobile;
		this.address = builder.address;
		this.salary = builder.salary;

	}

	public String getFirstName() {
		return firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public int getAge() {
		return age;
	}

	public long getMobile() {
		return mobile;
	}

	public String getAddress() {
		return address;
	}

	public double getSalary() {
		return salary;
	}

	public static class EmployeeBuilder {
		private String firstName;
		private String lastName;
		private int age;
		private long mobile;
		private String address;
		private double salary;

		public EmployeeBuilder(String firstName, String lastName, int age, long mobile) {
			this.firstName = firstName;
			this.lastName = lastName;
			this.age = age;
			this.mobile = mobile;
		}

		public EmployeeBuilder address(String address) {
			this.address = address;
			return this;
		}

		public EmployeeBuilder salary(double salary) {
			this.salary = salary;
			return this;
		}

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

	}

}


Now client can use this builder pattern as below

  1. package com.kb.builder;
  2.  
  3. public class BuilderClient {
  4.  
  5.     public static void main(String[] args) {
  6.        
  7. //case 1: Create Employee with all required and one optional attribute
  8.  Employee e1 =  new Employee.EmployeeBuilder("John", "Dian",28,9999888812l)
  9.                 .address("test address")
  10.                 .build();
  11.                
  12.                
  13. //case 2: Create Employee with all required and both optional attributes
  14.  Employee e2 =  new Employee.EmployeeBuilder("John", "Dian",28,9999888812l)
  15.                 .address("test address")
  16.                 .salary(40000)
  17.                 .build();
  18.  
  19.     }
  20.  
  21. }
package com.kb.builder;

public class BuilderClient {

	public static void main(String[] args) {
		
//case 1: Create Employee with all required and one optional attribute
 Employee e1 =  new Employee.EmployeeBuilder("John", "Dian",28,9999888812l)
			    .address("test address")
			    .build();
			   
			   
//case 2: Create Employee with all required and both optional attributes
 Employee e2 =  new Employee.EmployeeBuilder("John", "Dian",28,9999888812l)
			    .address("test address")
			    .salary(40000)
			    .build();

	}

}

We can see how easy it is to construct the object using Builder pattern

We can create object with required attributes and optional attributes as per the requirement by using build method appropriately.

Advantages of Builder pattern


1) It minimizes the number of parameters passed to constructor and also there is no need to pass null for optional parameters to the constructor

2) This pattern always instantiate the complete object rather than creating an object with incomplete state until the appropriate “setter” methods are called explicitly to set additional fields.

3) Client code is more readable and easy to create object

Disadvantages of Builder pattern


The number of lines in the code will be more as we need to construct the entire Builder object

About the Author

Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on