Builder Design Pattern in Java
What Problem Does Builder Solve?
Suppose we have a User class.
public class User {
private String name;
private int age;
private String email;
private String phone;
private String address;
}There are three common ways to create this object.
1. Using Constructors
User user = new User(
"Rajat",
26,
"rajat@gmail.com",
"999999999",
"Patna"
);Problems
- Hard to read.
- Difficult to remember parameter order.
- Easy to pass values in the wrong position.
- As optional fields increase, constructors multiply (Telescoping Constructor Problem).
Example
User(name)
User(name, age)
User(name, age, email)
User(name, age, email, phone)
User(name, age, email, phone, address)Too many constructors.
2. Using Setters
User user = new User();
user.setName("Rajat");
user.setAge(26);
user.setEmail("rajat@gmail.com");Problem:
The object exists even before it’s fully initialized.
For a moment,
User
name = null
age = 0
email = nullSomeone could accidentally use this incomplete object.
3. Builder Pattern
User user = User.builder()
.name("Rajat")
.age(26)
.email("rajat@gmail.com")
.build();Advantages
- Readable
- Optional fields are easy
- No constructor explosion
- Object is created only when complete
- Great for immutable objects
Main Idea
Builder Pattern creates an object step by step.
Instead of passing everything to a constructor,
we first collect values,
then finally create the object.
Builder
↓
Collect values
↓
build()
↓
User ObjectUser Class Code:
public class User {
private String name;
private int age;
// Constructor accepts Builder object
private User(UserBuilder builder) {
this.name = builder.name;
this.age = builder.age;
}
// Returns Builder object
public static UserBuilder builder() {
return new UserBuilder();
}
// Builder Class
public static class UserBuilder {
private String name;
private int age;
public UserBuilder name(String name) {
this.name = name;
return this;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public User build() {
return new User(this);
}
}
}Step 1
Understanding Every Part
User.builder();This does NOT create a User.
It creates a UserBuilder.
User.builder()
↓
new UserBuilder()Memory
UserBuilder
name = null
age = 0Step 2
.name("Rajat")This method executes
public UserBuilder name(String name) {
this.name = name;
return this;
}It stores
Builder
name = Rajat
age = 0Notice
return this;means ,Return the same Builder object.
No new Builder is created.
Step 3
.age(26)Again
this.age = age;
return this;Builder now becomes
Builder
name = Rajat
age = 26Again,the same Builder object is returned.
Why return this?
This enables method chaining.
Without it,this wouldn’t work
User.builder()
.name("Rajat")
.age(26);Because after calling .name(), Java wouldn't know what object to call .age() on.
Get Bappaditya Roy’s stories in your inbox
Join Medium for free to get updates from this writer.
return this simply says:
“I’m done with this method. Here is the same Builder object. Continue calling methods on it.”
Step 4
Finally
.build()executes
public User build() {
return new User(this);
}Here
thismeans ,Current Builder object which already contains
Builder
name = Rajat
age = 26Now Java executes
new User(builder)Step 5
The constructor receives the Builder.
private User(UserBuilder builder) {
this.name = builder.name;
this.age = builder.age;
}This simply copies data.
Builder
name = Rajat
age = 26
↓
Copy
↓
User
name = Rajat
age = 26Builder’s job is now finished.
Complete Flow
User user = User.builder()
.name("Rajat")
.age(26)
.build();Execution Flow
User.builder()
↓
Creates UserBuilder
↓
name("Rajat")
↓
Builder stores name
↓
return same Builder
↓
age(26)
↓
Builder stores age
↓
return same Builder
↓
build()
↓
new User(builder)
↓
Constructor copies values
↓
Final User Object CreatedMemory Diagram
User.builder() │
▼+----------------------+
| UserBuilder |
|----------------------|
| name = null |
| age = 0 |
+----------------------+ │
▼.name("Rajat")+----------------------+
| UserBuilder |
|----------------------|
| name = Rajat |
| age = 0 |
+----------------------+ │
▼.age(26)+----------------------+
| UserBuilder |
|----------------------|
| name = Rajat |
| age = 26 |
+----------------------+ │
▼.build()callsnew User(builder) │
▼+----------------------+
| User |
|----------------------|
| name = Rajat |
| age = 26 |
+----------------------+
Code
Why is builder() Static?
Because no User object exists yet.
If builder() were not static, you would need to write:
User user = new User();
user.builder();Making it static lets us call:
User.builder();Is builder() a Java Keyword?
No.
Java has no predefined builder() method.
This will not compile:
class User {
}
User.builder(); // ❌ Compilation ErrorThe builder() method is either:
- Written manually (as in this example), or
- Generated automatically by Lombok using
@Builder.
With Lombok:
@Builder
public class User {
private String name;
private int age;
}Behind the scene , lombok generates these
public static UserBuilder builder() {
return new UserBuilder();
}Interview Answer (2–3 Lines)
Builder Pattern is a creational design pattern used to construct complex objects step by step. It avoids telescoping constructors, improves readability through method chaining, supports optional parameters, and ensures the object is created only after all required data has been provided.
Easy Memory Trick
Think of ordering a custom burger.
You don’t receive the burger immediately.
You choose ingredients one by one:
Burger.builder()
↓
Bread()
↓
Cheese()
↓
Chicken()
↓
Extra Sauce()
↓
build()
↓
🍔 Final BurgerThe burger (User object) is created only after you’ve finished selecting everything.










