Builder Pattern Explained
Fast recall
Quick revision
Core answer
build() once. It is useful when positional constructors become hard to read, optional values need flexible ordering, or several inputs must be validated together. It is unnecessary for a small object with a clear constructor.Interview-ready guide
Interview answer
Builder pattern solves the telescoping constructor problem.
When you have a class with many fields and several are optional, you'd normally create multiple overloaded constructors for each combination. That becomes unreadable fast. Builder fixes this by letting you construct the object step-by-step using method chaining.
You create a static inner Builder class that mirrors the outer class fields. Required fields go in the Builder's constructor, and optional fields get their own setter methods that return this so you can chain calls. Then build() assembles the final object.
For example, say you're building an OrderRequest in a cart service with customer ID, items, payment method, discount code, gift wrap option, and delivery notes. Instead of six constructor overloads, you write order equals new OrderRequest dot Builder with customer ID and items, then chain dot paymentMethod, dot discountCode, dot giftWrap, and finally dot build. The outer class constructor is private, so Builder is the only way in.
One common mistake is using Builder for every class, even simple ones with two fields. That's overkill. Apply it when you have four-plus fields with several optional, or when you need immutability with complex construction.
In real Spring Boot apps, you see this pattern everywhere in request DTOs and configuration objects because it keeps code readable as requirements grow.
Builder Pattern Explained
Direct Answer
The Builder pattern separates a multi-step construction API from the object it creates. Callers supply named values to a builder and call build() once. It is useful when positional constructors become hard to read, optional values need flexible ordering, or several inputs must be validated together. It is unnecessary for a small object with a clear constructor.
Code Example
public class CartOrder {
private final Long customerId;
private final List<String> items;
private final String paymentMethod;
private final String discountCode;
private final boolean giftWrap;
private final String deliveryNotes;
private CartOrder(Builder builder) {
this.customerId = builder.customerId;
this.items = builder.items;
this.paymentMethod = builder.paymentMethod;
this.discountCode = builder.discountCode;
this.giftWrap = builder.giftWrap;
this.deliveryNotes = builder.deliveryNotes;
}
public static class Builder {
private final Long customerId; // required
private final List<String> items; // required
private String paymentMethod = "CREDIT_CARD";
private String discountCode;
private boolean giftWrap = false;
private String deliveryNotes;
public Builder(Long customerId, List<String> items) {
this.customerId = customerId;
this.items = items;
}
public Builder paymentMethod(String method) {
this.paymentMethod = method;
return this; // enables chaining
}
public Builder discountCode(String code) {
this.discountCode = code;
return this;
}
public Builder giftWrap(boolean wrap) {
this.giftWrap = wrap;
return this;
}
public Builder deliveryNotes(String notes) {
this.deliveryNotes = notes;
return this;
}
public CartOrder build() {
if (items.isEmpty()) {
throw new IllegalStateException("Order must have at least one item");
}
return new CartOrder(this);
}
}
}
Common Mistakes & Pitfalls
- Making the outer class constructor public: Freshers often leave the main class constructor public, which defeats the pattern's purpose — the Builder should be the only way to create instances, ensuring validation and consistency.
- Using Builder for simple objects: Applying Builder to classes with two or three fields adds boilerplate without value; just use a regular constructor or Lombok's @AllArgsConstructor for simple cases.
- Forgetting validation in build(): The build() method should validate that all required fields are set and throw IllegalStateException if not, but freshers often skip this, allowing creation of incomplete objects that fail later in unpredictable ways.
Check your understanding
Answer these without looking back at the article.
- What is Lombok's @Builder and how does it work?
- How does Builder enable immutable objects?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.