Suppose we have a class having many different properties or instance variables.
Creating an object of this class means providing a value to all these variables, which is a complex task.
Builder design pattern solves this problem by breaking the object creation process in several steps.

Below is a definition of this pattern

The Builder Design Pattern is a creational design pattern that separates the construction of a complex object from its representation.
It allows for the step-by-step creation of an object, making it easy to create and modify objects with many properties and variables.

In this article, we will understand Builder design pattern in detail.

How does Builder pattern work

Typically, to create an object with builder pattern, we create a separate class, called the Builder, that is responsible for constructing the object.
This Builder class is a nested inner class and
1. Has methods for setting the properties and variables of the object, allowing for step-by-step construction.
2. All the methods of this class return Builder object so that they can be chained.
3. Has a single method, called build() that returns an object of outer class.

Once the object is fully constructed, the Builder class returns it to the client, which can then use the object as needed.
The client never needs to know how the object was constructed, as this is handled entirely by the Builder class.

Outer class contains only getter methods for its properties so that they the object is immutable and the property values can not be altered after object creation.
Also, remember that the constructor of Car MUST be private so that object creation can only be done through Builder.

Builder design pattern example

Below is an example of Builder pattern which creates a complex object of class Car.

public class Car {
  private String make;
  private String model;
  private int year;
  private String color;
  private boolean hasSunroof;
  private boolean hasNavigation;

  public static class Builder {
    private String make;
    private String model;
    private int year;
    private String color;
    private boolean hasSunroof;
    private boolean hasNavigation;

    public Builder make(String make) {
      this.make = make;
      return this;
    }

    public Builder model(String model) {
      this.model = model;
      return this;
    }

    public Builder year(int year) {
      this.year = year;
      return this;
    }

    public Builder color(String color) {
      this.color = color;
      return this;
    }

    public Builder hasSunroof(boolean hasSunroof) {
      this.hasSunroof = hasSunroof;
      return this;
    }

    public Builder hasNavigation(boolean hasNavigation) {
      this.hasNavigation = hasNavigation;
      return this;
    }

    public Car build() {
      Car car = new Car();
      car.make = this.make;
      car.model = this.model;
      car.year = this.year;
      car.color = this.color;
      car.hasSunroof = this.hasSunroof;
      car.hasNavigation = this.hasNavigation;
      return car;
    }
  }

  /*
   * Private constructor
  */
  private Car() {}

  // getter methods
}

In this example, the Builder class is an inner class of Car having methods for setting the properties of the Car object.
Builder class has a build() method which returns a fully constructed Car object.

To use the Builder Design Pattern to create a Car object, we would create a new instance of the Builder class and call its methods to set the properties of the Car object as below

Car car = new Car.Builder()
    .make("Honda")
    .model("City")
    .year(2023)
    .color("Silver")
    .hasSunroof(true)
    .hasNavigation(true)
    .build();

Builder design pattern example 2

Below is another example of creating an object with builder design pattern in java.

public class Employee {
  private String firstName;
  private String lastName;
  private int age;
  private String address;

  public static class Builder {
    private String firstName;
    private String lastName;
    private int age;
    private String address;

    public Builder firstName(String firstName) {
      this.firstName = firstName;
      return this;
    }

    public Builder lastName(String lastName) {
      this.lastName = lastName;
      return this;
    }

    public Builder age(int age) {
      this.age = age;
      return this;
    }

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

    public Employee build() {
      Employee employee = new Employee();
      employee.firstName = this.firstName;
      employee.lastName = this.lastName;
      employee.age = this.age;
      employee.address = this.address;
      return employee;
    }
  }

  private Employee() {}
  
  // getters methods
}

In this example, the Employee class is the complex object that we want to build.
Builder class is an inner class of Employee and it has methods for setting the properties of the Employee object.
build() method in the Builder class returns a fully constructed Employee object.

To use the Builder Design Pattern to create a Employee object, we would create a new instance of the Builder class and call its methods to set the properties of the Employee object as shown below

Employee person = new Employee.Builder()
    .firstName("Abc")
    .lastName("Xyz")
    .age(30)
    .address("111 Wxy")
    .build();

Benefits of Builder design pattern

Following are some of the benefits that you will notice while designing your classes with builder pattern.

1. Separation of concerns

Builder design pattern maintains the logic of constructing an object inside a separate method.
The client or the code that creates the object is not aware about how the object is being constructed.

2. Simplifies object construction

Builder Design Pattern simplifies object construction by allowing objects to be created step-by-step.
This means that the object can be constructed in a more flexible and modular way.
This is especially useful for objects with many properties or for objects that require complex initialization.

3. Promotes Immutability

Builder Design Pattern encourages immutability, which means that once an object is constructed, its state cannot be changed.
This can help to prevent bugs and make the code more reliable because it reduces the risk of accidental modifications to the object state.

4. Fluent interface

Builder Design Pattern provides a fluent interface, which means that the code for constructing an object reads like a series of sentences or phrases.
This can make the code more readable and easier to understand, especially for new developers who are not familiar with the codebase.

5. Reduces constructor complexity

Builder Design Pattern can help to reduce the complexity of constructors by moving the logic of constructing an object to a separate builder class.
This can make the constructor code cleaner and easier to maintain.


Builder pattern disadvantages

There are a few downsides of using builder pattern in java as listed below

1. Increased code complexity

Builder Design Pattern adds an additional layer of abstraction to the code, which can make it more complex and harder to understand.

2. Additional code overhead

Builder Design Pattern requires the creation of additional classes and methods, which can increase the amount of code in the program.
This can make the codebase larger and more complex, which can make it harder to maintain.

3. Extra object creation

Builder Design Pattern can have a slight performance impact because it involves the creation of additional objects. In some cases, this overhead may be negligible, but in high-performance applications, it may be a concern.

4. Limited use for simple objects

Builder Design Pattern is suitable for creating complex objects with many properties.
It should not be used for simple objects with only a few properties.

That is all on Builder design pattern in java to create objects. Hope the article was useful.