Sitemap

Builder Design Pattern in Java

4 min readJul 24, 2026

--

Press enter or click to view image in full size

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 = null

Someone 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 Object

User 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 = 0

Step 2

.name("Rajat")

This method executes

public UserBuilder name(String name) {

this.name = name;

return this;
}

It stores

Builder

name = Rajat
age = 0

Notice

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 = 26

Again,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

this

means ,Current Builder object which already contains

Builder
name = Rajat
age = 26

Now 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 = 26

Builder’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 Created

Memory 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

https://github.com/Bappa21ditya/javaProject/tree/main/src/main/java/com/security/java_project/system_design/patterns/builderPattern

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 Error

The 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 Burger

The burger (User object) is created only after you’ve finished selecting everything.

--

--