Introduction:
Each design pattern comes to solve a well known problem.
Builder Design Patter the Problem is :
There is a class that has a lot of variables inside the builder. Suppose we have a Student class and it has a constructor that contains 10 variables of different types. When one of the team members wants to create an object of the class, he will face some difficulties due to a large number of variables.
So the Builder Design Pattern was developed to solve this problem by providing a method that does not contain variables and uses the other setter to fill in the necessary parameters for the constructor.
Simple Example :
We want to apply the Builder Design Pattern to the example of Student.
public class Student {
private int id;
private String name;
private String major;
private String mobileNumber;
private double salary;
// Optional Private Constructor
pu Student(int id, String name, String major, String mobileNumber) {
this.id = id;
this.name = name;
this.major = major;
this.mobileNumber = mobileNumber;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
public String getMobileNumber() {
return mobileNumber;
}
public void setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
To Apply Builder Design Patter we need a New Class to Collect Data Variables and after the user fills all parameter data we Create Object from Student Class so we need to Declare ‘SimpleStudentBuilder’ class.
Notes :
We need to Declare this class ‘SimpleStudentBuilder’ inner in Student Class because we need to change Student Constructor to private and an inner class, we can init the new object form Student.
We Need also Declare ‘SimpleStudentBuilder’ Static because we can use it from outer class and not init object from student :)
SimpleStudentBuilder Class:
// This Class inner in Student class
public static class SimpleStudentBuilder {
private int id;
private String name;
private String major;
private String mobileNumber;
private double salary;
public SimpleStudentBuilder() {
}
public SimpleStudentBuilder setId(int id) {
this.id = id;
return this;
}
public SimpleStudentBuilder setName(String name) {
this.name = name;
return this;
}
public SimpleStudentBuilder setMajor(String major) {
this.major = major;
return this;
}
public SimpleStudentBuilder setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
return this;
}
public SimpleStudentBuilder setSalary(double salary) {
this.salary = salary;
return this;
}
public Student build() {
// TODO : Check All Require Parameters is not null
if (id == 0)
throw new NullPointerException("Id Can't be with out value");
if (name == null)
throw new NullPointerException("Name Can't be Null");
if (major == null)
throw new NullPointerException("Major Can't be Null");
if (mobileNumber == null)
throw new NullPointerException("Number Can't be Null");
Student student = new Student(id, name, major, mobileNumber);
student.salary = salary;
return student;
}
}
you can show full code in the GitHub repository.
Usage SimpleStudentBuilder :
public static void main(String[] args) {
Student student = new Student.SimpleStudentBuilder()
.setMajor("IT")
.setName("Kareem Radwa")
.setMobileNumber("0597190510")
.setSalary(1000)
.setId(32)
.build();
}
Deep In Builder Design Patter :)
Suppose in Student Constructor we have priority in passing parameter values for example in order [ id, name, major, mobile number ] If this arrangement disappears you will not be able to create an Object from Class Student.
so we need to answer to this situation the answer is Step Builder, but how we can implement this answer. keep reading :)
Step Builder Design Patter :
To apply this idea you need
A number of interfaces with the same number of Require variables so in Our example Student class we need 4 interfaces and in addition, we need one more interface for Build Method and optional variables.
Class is implemented all the above interfaces we need captions this ‘Steps’
The explanation for Usage StudentStepBuilder:
When we need to use this approach of builder you need to show in first time only id set method and if the user fil it, you can after that set Name variable value, etc.
Time Of coding:
public class StudentStepBuilder {
public static IdFiled newBuilder() {
return new Steps();
}
public static interface IdFiled {
NameFiled setId(int id);
}
public static interface NameFiled {
MajorFiled setNmae(String name);
}
public static interface MajorFiled {
MobileNumber setMajor(String major);
}
public static interface MobileNumber {
BuildStep setMobile(String mobile);
}
public static interface BuildStep {
BuildStep setSalary(double salary);
Student build();
}
private static class Steps implements IdFiled, NameFiled, MajorFiled, MobileNumber, BuildStep {
private int id;
private String name;
private String major;
private String mobileNumber;
private double salary;
@Override
public NameFiled setId(int id) {
this.id = id;
return this;
}
@Override
public MajorFiled setNmae(String name) {
this.name = name;
return this;
}
@Override
public MobileNumber setMajor(String major) {
this.major = major;
return this;
}
@Override
public BuildStep setSalary(double salary) {
this.salary = salary;
return this;
}
@Override
public BuildStep setMobile(String mobile) {
this.mobileNumber = mobile;
return this;
}
@Override
public Student build() {
if (id == 0) {
throw new NullPointerException("ID Can't be 0");
}
if (name == null) {
throw new NullPointerException("Name can't be null");
}
if (major == null) {
throw new NullPointerException("Major can't be null");
}
if (mobileNumber == null) {
throw new NullPointerException("Mbile Number can't be null");
}
Student student = new Student(id, name, major, mobileNumber);
student.setSalary(salary);
return student;
}
}
}
Usage StudentStepBuilder:
Result of Step Builder Design Pattern
all code in GitHub repository: link
Finally
This is the First Article for me. I wish happy when you reading it.
Top comments (12)
As an Study topic is really, really good! I really wish that when I was studying, I would have been able to read this...
Well, as @frmaglia sugested, on work you can use the Immutables lib or the polemic Project Lombok, we use it at the company that I work and it really saves development time.
Anyway, good article! Congratulations!
thank you very much for this reply.
I am thinking of writing a detailed article for every design pattern in advanced
Good article. Sad that Builder itself is anti-pattern in most cases, including one used by you in examples. dev.to/siy/when-builder-is-anti-pa...
Hi Sergiy, I am very happy for your reply.
But in the Builder Design Pattern:
1- The constructor can't must be private . so you can still constructor public and any developer use it and fill all require parameters.
2- I agree with you to the extent that error in compile time is better than an error in Run Time.
But in the case of my article, look at the last example. The developer cannot see the setMajor method except if it calls the setName method for example.
I think we can overcome the problem of forgetting some data without entering.
1- Yes, but this is written in Design patterns constructor can be optional private as I remember.
2- for point two you can use Immutables lib (immutables.github.io/immutable.html) and have it for free as some readers mention above. :).
Thank you very much, Mr Sergiy
Yes, I agree with you,
But I explain how Builder and Step Builder work.
thank you.
You can avoid the hassle of doing it manually by using Immutables lib (immutables.github.io/immutable.html) and have it for free.
Does Intellij work well with this library?
Autocompletes, go to definition, etc...
oh, thank you very very much.
But in this article, I explain it to other students because I'm a student and I get this topic in university.
Hi Kareem, thanks for the article! It gave me inspiration for my Typescript project which uses inner classes.