Builder pattern in Java

Introduction to design patterns:

What is a design pattern?

It is best practise and a proper solution to a problem faced by software developers this solution based on two principles of object oriented design .

  1. Program to an interface not an implementation.
  2. Preferring object composition over class inheritance. Object can be decomposed to types e.g Telephone has an object Ring through Implementation not inheritance.

Types of Design Patterns:

Type Description
Behavioral It describes the communication between objects (e.g., Observer Pattern, Command Pattern and State Pattern).
Creational It describes the way of creating object without revealing the creation logic (e.g., Factory Pattern, Builder Pattern and Singleton Pattern).
Structural It describes the way of composition object and classes to construct large system )e.g., Proxy Pattern, Facade Pattern and Adapter Pattern).
 


What is builder pattern?

It is an object creational way aims to eliminate telescoping constructor when there are many parameters to set to an object and most of them are optional.

Take a look at this example of Employee class:

package com.emaraic.tests;
 
 /**
  *
  * @author Taha Emara 
  * Website: http://www.emaraic.com
  * Email : taha@emaraic.com
  * Created on: May 24, 2016
  */
 public class Employee {
 
     private long id;
     private String name;
     private String birthday;
     private int department;
     private String address;  //optional parameter
 
     public Employee() {
     }
 
     public Employee(long id, String name, String birthday, int department) {
         this.id = id;
         this.name = name;
         this.birthday = birthday;
         this.department = department;
     }
 
     public Employee(long id, String name, String birthday, int department, String address) {
         this.id = id;
         this.name = name;
         this.birthday = birthday;
         this.department = department;
         this.address = address;
     }
 
     public String getAddress() {
         return address;
     }
 
     public long getId() {
         return id;
     }
 
     public String getName() {
         return name;
     }
 
     public String getBirthday() {
         return birthday;
     }
 
     public int getDepartment() {
         return department;
     }
 
     public void setAddress(String address) {
         this.address = address;
     }
 
     public void setId(long id) {
         this.id = id;
     }
 
     public void setName(String name) {
         this.name = name;
     }
 
     public void setBirthday(String birthday) {
         this.birthday = birthday;
     }
 
     public void setDepartment(int department) {
         this.department = department;
     }
 
     @Override
     public String toString() {
         return "Employee{" + "id=" + id + ", name=" + name + ", birthday=" + birthday + ", department=" + department + ", address=" + address + '}';
     }
  
 }
 


There are two ways of creating an object from this class:

1- Using telescoping constructors and you will notice that is is hard to write and also to read in a case of large number of parameters and worse with many optional parameters.

package com.emaraic.tests;
 
 public class TestEmp {
 
     public static void main(String[] args) {
         //telescoping way
         Employee emp = new Employee(10, "Taha", "1/7/1991", 1);
         Employee emp1 = new Employee(10, "Taha", "1/7/1991", 1, "Egypt");
         System.out.println(emp1);
     }
 }
 


2-Using JavaBeans Pattern (Beans=default constructor+Setters+Getters+no public arguments) but you notice that it is a wordy way and also buggy because you may call the get method and get null because you forgot to call the set method with the proper parameter and it may take a time to write but now thanks to new IDEs.

package com.emaraic.tests;
 
 public class TestEmp {
 
     public static void main(String[] args) {
         //setter way
         Employee emp2 = new Employee();
         emp2.setId(10);
         emp2.setName("Taha");
         emp2.setBirthday("1/7/1991");
         emp2.setDepartment(1);
         emp2.setAddress("Egypt");
         System.out.println(emp2);
     }
 }
 


From this point you must think about builder pattern but keep in your mind that you must create a Builder class for every bean as you will see.


How do we create it?

Add a static Builder class which we use to set parameters of Employee and also build it in this way.

package com.emaraic.tests;
 
 /**
  *
  * @author Taha Emara 
  * Website: http://www.emaraic.com
  * Email : taha@emaraic.com
  * Created on: May 24, 2016
  */
 public class Employee {
 
     private long id;
     private String name;
     private String birthday;
     private int department;
     private String address;  //optional parameter
 
     public String getAddress() {
         return address;
     }
 
     public long getId() {
         return id;
     }
 
     public String getName() {
         return name;
     }
 
     public String getBirthday() {
         return birthday;
     }
 
     public int getDepartment() {
         return department;
     }
 
     public void setAddress(String address) {
         this.address = address;
     }
 
     public void setId(long id) {
         this.id = id;
     }
 
     public void setName(String name) {
         this.name = name;
     }
 
     public void setBirthday(String birthday) {
         this.birthday = birthday;
     }
 
     public void setDepartment(int department) {
         this.department = department;
     }
 
     @Override
     public String toString() {
         return "Employee{" + "id=" + id + ", name=" + name + ", birthday=" + birthday + ", department=" + department + ", address=" + address + '}';
     }
 
     static class Builder {
 
         private long id;
         private String name;
         private String birthday;
         private int department;
         private String address;  //optional parameter
 
         public Builder id(int id) {
             this.id = id;
             return this;
         }
 
         public Builder name(String name) {
             this.name = name;
             return this;
         }
 
         public Builder birthday(String birthday) {
             this.birthday = birthday;
             return this;
         }
 
         public Builder department(int department) {
             this.department = department;
             return this;
         }
 
         public Builder adress(String address) {
             this.address = address;
             return this;
         }
 
         public Employee build() {
             Employee emp = new Employee();
 
             emp.setId(this.id);
             emp.setName(this.name);
             emp.setAddress(this.address);
             emp.setBirthday(this.birthday);
             emp.setDepartment(this.department);
             
             return emp;
         }
 
     }
 
     public static void main(String[] args) {
 
         //telescoping way
         Employee emp = new Employee(10, "Taha", "1/7/1991", 1);
         Employee emp1 = new Employee(10, "Taha", "1/7/1991", 1, "Egypt");
         System.out.println(emp1);
         //setter way
         Employee emp2 = new Employee();
         emp2.setId(10);
         emp2.setName("Taha");
         emp2.setBirthday("1/7/1991");
         emp2.setDepartment(1);
         emp2.setAddress("Egypt");
         System.out.println(emp2);
 
         //builder pattern way 
         Employee emp3 = new Employee.Builder().id(10).name("taha").birthday("1/7/1991").department(1).adress("Egypt").build();
         System.out.println(emp3);
     }
 }
 

References
:
  1. Effective Java (Book).
Share: