Builder Design Pattern

The Builder design pattern provides a simple way to construct complex objects using a step by step approach. A Builder creates parts of the complex object every time it is called and maintains the intermediate state of complex object. When the object creation finishes, client retrieves the object from the Builder.

A builder class separates the construction of a complex object from its representation so that the same construction process can create different representations.

Advantages of Builder Pattern

  • Builder pattern also helps minimizing the number of parameters in constructor are provides highly readable method calls.
  • It encapsulates the logic of creating a complex object.
  • It allows us to create a complex object step by step.
  • Always fully constructed object will be available to client. rather than returning an incomplete object even if developer has not set all member fields.
  • Easy to maintain if number of fields required to create object is more.

When we should use Builder Pattern

  • When we needs different representations for the objects that are being built. Builder class provides a way to configure an object before creating it.
  • The algorithm of creating a complex object is independent from the parts that actually compose the complex object.
  • Once an object is fully created, you don’t want to change it’s state.

Implementation of Builder Design Pattern

  • We will create an Employee class containing employee information and a static nested class called EmployeeBuilder inside the Employee class whose object will be build Employee objects.
  • Employee class must provide only public getter functions not setter function to ensure that employee object is immutable form outside.
  • EmployeeBuilder class will have same set of fields as Employee class.
  • EmployeeBuilder class will expose public method for setting all optional fields of EmployeeBuilder class. All setter functions will return a reference to current builder object.
  • build() method of EmployeeBuilder class will create a new instance of Employee object by passing it self as constructor parameter. Constructor will copy the fields from builder object to Employee object. Clients will call build() method once they finished setting fields of builder.

Builder Design Pattern

Employee.java
public class Employee {
    private final String name;           // Required
    private final String department;     // Optional
    private final int age;               // Optional
    private final int salary ;           // Optional
    private final String rank;           // Optional
  
    private Employee(EmployeeBuilder builder) {
        this.name = builder.name;
        this.department = builder.department;
        this.age = builder.age;
        this.salary = builder.salary;
        this.rank = builder.rank;
    }
  
    // we will only provide public getters to ensure that 
    // object is immutable
    public String getName() {
        return this.name;
    }
    public String getDepartment() {
        return this.department;
    }
    public int getAge() {
        return this.age;
    }
    public int getSalary() {
        return this.salary;
    }
    public String getRank() {
        return this.rank;
    }
  
    public static class EmployeeBuilder
    {
        private final String name;
        private String department;
        private int age;
        private int salary;
        private String rank;
  
        public EmployeeBuilder(String name) {
            this.name = name;
        }
         
        public EmployeeBuilder setDepartment(String department) {
            this.department = department;
            return this;
        }
         
        public EmployeeBuilder setAge(int age) {
            this.age = age;
            return this;
        }
         
        public EmployeeBuilder setSalary(int salary) {
            this.salary = salary;
            return this;
        }
        public EmployeeBuilder setRank(String rank) {
            this.rank = rank;
            return this;
        }
         
        //Return the constructed Employee object to client 
        public Employee build() {
            return new Employee(this);
        }
    }
     
    @Override
    public String toString(){
        return  "Name : " + this.name + "\nDepartment : " + 
        this.department + "\nAge : " + this.age + "\nSalary : "
        + this.salary + "\nRank : " + this.rank;
    }
}

Builder Design Pattern 1

BuilderPatternDemo.java
public class BuilderPatternDemo {
    public static void main(String[] args) {
        // creating Employee object by setting all fields 
        Employee emp1 = new Employee.EmployeeBuilder("George")
            .setDepartment("Finance").setAge(35).setSalary(30000)
            .setRank("2").build();
        System.out.println(emp1.toString() + "\n");
         
        // creating Employee object by setting only 3 fields 
        Employee emp2 = new Employee.EmployeeBuilder("Mark")
            .setDepartment("Finance").setAge(35).build();
        System.out.println(emp2.toString() + "\n");
         
        // creating Employee object by setting only 1 field 
        Employee emp3 = new Employee.EmployeeBuilder("Andy").build();
        System.out.println(emp3.toString() + "\n");
    }
}

Output

Name : George
Department : Finance
Age : 35
Salary : 30000
Rank : 2

Name : Mark
Department : Finance
Age : 35
Salary : 0
Rank : null

Name : Andy
Department : null
Age : 0
Salary : 0
Rank : null