Builder Pattern
20 Jul 2020Contents
What is Builder Pattern?
Builder design pattern separates the construction of a complex object from its representation so that the same construction process can create different representations.
AbstractClass
: Abstract interface for creating objects (product)ConcreteClass
: The implementation class of the builder. A class that allows you to create other objects. Create and assemble parts to create objects.Director
: Director class is responsible for the precise sequence of object creation. This class takes ConcreteBuilder as a parameter and performs the necessary actions.Product
: Final objects created by Director using Builder.
Why use Builder Pattern?
- Encapsulates code for construction and representation.
- Provides control over steps of construction process.
- Create objects without creating unnecessary constructors.
- Create objects regardless of the order of the data.
When creating an instance, it is difficult to create only through the constructor
.
Assigning too many parameters to the constructor makes it difficult to determine which factor represents which value. In some instances, it may be necessary to create only a specific parameter. In this case, the value corresponding to a particular parameter must be passed to null, which is very bad in terms of the readability of the code.
public Student(long cwid, String name, String major, int age, String email) {
this.cwid = cwid;
this.name = name;
this.major = major;
this.age = age;
this.email = email;
}
If we use this constructor to create an student instance.
It should be like this:
Student student = new Student(888801234, "john", "CS", 22, "john1234@gmail.com");
But you may only know the student’s ID and name. At this case, the gargage data
or null value
must be passed over to the constructor’s parameter.
Student student = new Student(888801234, "john", null, 0, null);
But, it is difficult to determine what value a particular parameter represents. This is why we use a builder pattern.
Instead of creating the required objects directly from the client, create the builder object by passing over the required parameters, and then call the defined methods on the builder object to create an instance.
Problems
- Adding object creation is easy, but adding new parts that construct an object is difficult.
- Requires creating a separate
ConcreteBuilder
for each different type of product
Example
To implement Builder Pattern
- First, Create the builder class as a
Static Nested Class
. Use theBuilder
keyword for the class you want to create. For example, the name of the student class for the Computer class is StudentBuilder. - The constructor of the builder class uses the
public
keyword. Essential parameters are passed over as paramerters of the constructor. - Use method for nonessential parameter. The return value of the method must be the builder object itself.
- Finally, define a build() method within the builder class to provide object creation. And, it should use
private
keyword to create an object only through build().
Here, the Student class has only the getter method
without the setter method, and there is no public constructor
. Therefore, getting a Student object is only possible through the StudentBuilder class.
The id
and name
are essential parameters. And, others are optional parameters.
public class Student {
private long id;
private String name;
private String major;
private int age;
private String email;
public Student() {
}
@Override
public String toString() {
return "Student [id]: " + id + " [name]: " + name + " [major]: " + major + " [age]: " + age + " [address]: "
+ email;
}
public static class StudentBuilder {
// Essential parameter
private final long id;
private final String name;
// Selective parameter
private String major = "";
private int age = 0;
private String email = "";
public StudentBuilder(long id, String name) {
this.id = id;
this.name = name;
}
public StudentBuilder major(String major) {
this.major = major;
return this;
}
public StudentBuilder age(int age) {
this.age = age;
return this;
}
public StudentBuilder email(String email) {
this.email = email;
return this;
}
public Student build() {
return new Student(this);
}
}
private Student(StudentBuilder builder) {
this.id = builder.id;
this.name = builder.name;
this.major = builder.major;
this.age = builder.age;
this.email = builder.email;
}
}
Let’s use the StudentBuilder.
public class Client {
public static void main(String[] args) {
Student s1 = new Student.StudentBuilder(888801234, "John").major("Computer Science").age(22)
.email("john1234@gmail.com").build();
System.out.println(s1);
}
}
Output
You can create object like this. As you can see, the StudentBuilder class is used to create the Student object s1
.
888801234
is John
’s ID, and both parameters are essential. major
, age
, email
are optional. Finally, build()
creates and returns the object.