Builder design pattern in Java with example.

The Builder design pattern is a creational pattern that helps limit an objects complexity. This helps immensely with immutable objects with tons of properties in your application. Immutable objects are objects that don’t change, once you create them, you can’t change them. A immutable Java object must have private final fields. You would also instantiate the object and provide all of the properties in the constructor. This means you won’t use setters to set the properties in the object. This becomes a problem when you have multiple properties and only a few are required. Lets look at a quick example.

Say you have an Employee class with five properties (id, firstName, lastName, title, birthdate) in which you want immutable. Let’s also say that you can instantiate an Employee object while only specifying the id. This would require two constructors, one that takes in all of the properties and one that takes in the id only. This can go on and can get quite messy, especially when more properties are added to the Employee object

This is when the Builder design pattern comes in handy. Lets convert this class into a builder class in steps.

public class Employee {
    
    //properties that are only accessible within the Employee class
    private final int id;
    private final String firstName;
    private final String lastName;
    private final String title;
    private final String birthdate;

    //Constructor that takes in an id only. We still have to set the other properties.
    public Employee(int id){
        this.id = id;
        this.firstName = "";
        this.lastName = "";
        this.title = "";
        this.birthdate = "";
    }
    
    //Constructor that takes in id, firstname, and lastname
    public Employee(int id, String firstName, String lastName) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.title = "";
        this.birthdate = "";
    }

    //Constructor that takes in all properties.
    public Employee(int id, String firstName, String lastName, String title, String birthDate) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.title = title;
        this.birthdate = birthDate;
    }
}

1. Let’s remove the constructors except for the main constructor that takes in a Builder object and assign the variables like so. The builder object will contain all of the properties in the Employee which we will create next. We will also make the constructor private.

public class Employee {

    private final int id;
    private final String firstName;
    private final String lastName;
    private final String title;
    private final String birthdate;

    private Employee(Builder builder) {
        this.id = builder.id;
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.title = builder.title;
        this.birthdate = builder.birthDate;
    }
}

2. Add a static inner class within Employee called Builder. Add all the properties and only make the id final because it will be set in the constructor. We then create setters within the builder class that we can only set when we create the object, I will demonstrate that shortly. The build() method will return the Employee object that we put together.

public class Employee {

    private final int id;
    private final String firstName;
    private final String lastName;
    private final String title;
    private final String birthdate;

    private Employee(Builder builder) {
        this.id = builder.id;
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.title = builder.title;
        this.birthdate = builder.birthDate;
    }

    public static class Builder {
        private final int id;
        private String firstName;
        private String lastName;
        private String title;
        private String birthdate;

        public Builder(int id) {
            this.id = id;
        }

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

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

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

        public Builder setBirthDate(String birthDate) {
            this.birthdate = birthDate;
            return this;
        }

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

3. Add your getters to the Employee class so you can access any of the properties.

public class Employee {

    private final int id;
    private final String firstName;
    private final String lastName;
    private final String title;
    private final String birthdate;

    private Employee(Builder builder) {
        this.id = builder.id;
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.title = builder.title;
        this.birthdate = builder.birthDate;
    }

    public int getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getTitle() {
        return title;
    }

    public String getBirthdate() {
        return birthdate;
    }

    public static class Builder {
        private final int id;
        private String firstName;
        private String lastName;
        private String title;
        private String birthDate;

        public Builder(int id) {
            this.id = id;
        }

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

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

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

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

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


4. Now lets build your objects! In the main method, create new Employee objects like so. You will build the Employee objects at one time and set whatever properties you want. The only required property is the id and that will be passed into the constructor. .build() will return the Employee object that you created! Once you create your employee object, you will not be able to set properties which makes it immutable!

public class Main {

    public static void main(String[] args) {
        Employee employee = new Employee.Builder(1)
                .setFirstName("Tom")
                .setLastName("Brady")
                .build();

        System.out.println("Employee Id: " + employee.getId());
        System.out.println("Employee Name: " + employee.getFirstName() + " " + employee.getLastName());

        Employee employee2 = new Employee.Builder(2)
                .setFirstName("Peyton")
                .setLastName("Manning")
                .setBirthDate("01-01-1976")
                .setTitle("Quarterback")
                .build();

        System.out.println("Employee Id: " + employee2.getId());
        System.out.println("Employee Name: " + employee2.getFirstName() + " " + employee2.getLastName());
        System.out.println("Employee Birthdate: " + employee2.getBirthdate());
        System.out.println("Employee Title: " + employee2.getTitle());

    }
}


Try creating your own objects to get a better understanding. When you want to add a new property, salary for example, you would have to add it to the Employee class, the constructor, Builder class, and your getter/setter.

public class Employee {

    private final int id;
    private final String firstName;
    private final String lastName;
    private final String title;
    private final String birthdate;
    //new property
    private final int salary;

    private Employee(Builder builder) {
        this.id = builder.id;
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.title = builder.title;
        this.birthdate = builder.birthDate;
        //new property
        this.salary = builder.salary;
    }

    public int getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getTitle() {
        return title;
    }

    public String getBirthdate() {
        return birthdate;
    }

    //new getter for salary
    public int getSalary() {
        return salary;
    }

    public static class Builder {
        private final int id;
        private String firstName;
        private String lastName;
        private String title;
        private String birthDate;
        //salary property
        private int salary;

        public Builder(int id) {
            this.id = id;
        }

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

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

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

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

        //new setter for salary
        public Builder setSalary(int salary) {
            this.salary = salary;
            return this;
        }

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