Builder Design Pattern
Deep dive into the Builder Design Pattern with real-world examples
The Builder Design Pattern in Java is a powerful creational pattern used to create immutable objects with clean and readable code. It solves the problem of constructors overloaded with too many parameters — especially nulls — by giving you a step-by-step object construction mechanism. Here we take a very simple example of us sending emails over Gmail. What happens is whenever we send an email, once the email is sent, we cannot change the content of the email.So, what we will be doing here is to understand the email object construction with the optional fields and along with that the string builder class.
Email.java
@Getter //It is used to make it immutable. @Setter is used to make it mutable
public class Email {
private String to;
private String subject;
private String body;
private String cc;
private String bcc;
private List<String> attachments;
public Email(String to, String subject, String body, String cc, String bcc, List<String> attachments){
this.to = to;
this.subject = subject;
this.body = body;
this.cc = cc;
this.bcc = bcc;
this.attachments = attachments;
}
}
Taking the following example here what happens is when we create our main Java class there are many attributes that we take and what happens is sometimes there are some attributes such as attachments BCC or CC which are null. Now this happens for a single set of emails.what will happen is it will use a lot of null values and that is not a good system design to go forward with. So, to eliminate this entire problem of having more null values we use the builder design pattern.
Email.java
@Getter
public class Email {
private String to;
private String subject;
private String body;
private String cc;
private String bcc;
private List<String> attachments;
//We let the builder initialize the Email object
Email(EmailBuilder builder){
this.to = builder.getTo();
this.subject = builder.getSubject();
this.body = builder.getBody();
this.cc = builder.getCc();
this.bcc = builder.getBcc();
this.attachments = builder.getAttachments();
}
}
@Getter
public class EmailBuilder(){
private String to;
private String subject;
private String body;
private String cc;
private String bcc;
private List<String> attachments = new ArrayList<>();
//These are Setters
public EmailBuilder setTo(String to){
this.to = to;
return this;
}
public EmailBuilder setSubject(String subject){
this.to = subject;
return this;
}
public EmailBuilder setBody(String body){
this.body = body;
return this;
}
public EmailBuilder setCc(String cc){
this.cc = cc;
return this;
}
public EmailBuilder setBcc(String bcc){
this.bcc = bcc;
return this;
}
public EmailBuilder addAttachment(String attachment){
this.attachment = attachment;
return this;
}
public Email build(){
return new Email(builder: this);
}
}
Main.java
public class Main{
public static void main(String[] args){
EmailBuilder builder = new EmailBuilder();
Email email = builder
.setTo("addacoding01@gmail.com")
.setSubject("Request for AI content")
.setBody("Hi Coding Adda, ...")
.build();
// Email is immutable as it does not have setters and attributes are private
}
}
So as we see on the main.java function that it will not now go for creating null values for the attributes which are not defined rather what it will do is it will directly build it and here the email is immutable as it does not have any setter or and the attributes are private. This is the reason we are using the builder pattern to reduce the need of having very complex classes and also implementing things step by step which also helps us to avoid the issue of constructor explosion.