Java Builder design pattern

Here we will talk about the Java Builder design pattern, where and how it should be used.

This type of design pattern is also known as creational design pattern and is used in creating and configuring complex object from simple objects. So basically it helps us to write readable, manageable and understandable code while producing complex objects.

Builder pattern generates a build object which is used to construct a complex object which is called the product. To give the textbook definition, “Builder design pattern separates the construction of a complex object from its representation so that the same construction process can create different representations.”

Factory design pattern is also a creational design pattern. A step-by-step approach is strictly followed while generating the complex object using simple objects. This design pattern was created to resolve the issues generated by the factory and abstract factory design pattern when the objects consisted of a lot of attributes.

Where do we normally use builder design pattern?

  • When multiple representations of objects are required
  • Too many argument to pass from client
  • Object creation contains optional parameter

This type of design pattern is often implemented with a fluent interface.




Implementation of the builder design pattern

Each class in Java has a constructor set up either by the user explicitly or by default. Builder pattern is used when an object can be created with the help of a lot of different parameters which maybe mandatory while others maybe optional as well. Things get complicated and prone to error in this kind of situation. So, builder pattern comes in handy in this situation.

Steps while implementing builder design patter:

  1. Create a builder class with all the required fields
  2. Builder class should have a public constructor with all the required parameters
  3. Create methods to get the values of optional parameters. These methods should return the same builder object after setting the optional attribute.
  4. Finally provide a build() method in the builder class which will return the desired object.

Let us look at a coding example on how the builder pattern can be implemented while creating a complex object. We have considered a student data collection system and have created a Student class which deals with this particular data collection. A builder class called StudentBuilder has been generated and implemented as shown.

 

Let us look at an example:

public class Student {
    private int id;
    private String firstName;
    private String lastName;
    private int age;
    private String phone;
    private String address;
    private String course;

   public Student(StudentBuilder studentBuilder) {
        this.id = studentBuilder.id;
        this.firstName = studentBuilder.firstName;
        this.lastName = studentBuilder.lastName;

        this.age = studentBuilder.age;
        this.phone = studentBuilder.phone;
        this.address = studentBuilder.address;
        this.course = studentBuilder.course;
    }

    public int getId() {
        return id;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    public String getPhone() {
        return phone;
    }

    public String getAddress() {
        return address;
    }
    
   public String getCourse() {
        return course;
    }

    @Override
    public String toString() {
        return "Student{" +
               "id=" + id +
               ", firstName='" + firstName + '\'' +
               ", lastName='" + lastName + '\'' +
               ", age=" + age +
               ", phone='" + phone + '\'' +
               ", address='" + address + '\'' +
              ", course='" + course + '\'' +
               '}';
    }

    public static class StudentBuilder {

        private int id;
        private String firstName;
        private String lastName;
        private int age;
        private String phone;
        private String address;
        private String course;

        public StudentBuilder(int id, String firstName, String lastName) {
            this.id = id;
            this.firstName = firstName;
            this.lastName = lastName;
        }

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

        public StudentBuilder withOptionalPhone(String phone) {
            this.phone = phone;
            return this;
        }

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

        public Student buildStudent() {
            validateStudentData();
            return new Student(this);
        }

        private boolean validateStudentData() {
            //Validation process, check if student is registered in the database
            return true;
        }
    }
}

 

Use of builder in main code:

Student stu1 = new Student.StudentBuilder(12341, "Jack", "Harrison")
                .withOptionalAddress("Address")
                .withOptionalAge(21)
                .withOptionalPhone("874116073648")
                .buildStudent();
System.out.println("Student : " + stu1.toString());
Student stu2 = new Student.StudentBuilder(1225, "Diana", "Daniels")
                .withOptionalAge(18)
                .buildStudent();
System.out.println("Student : " + stu2);

 

 

Leave a Reply

avatar