Builder Pattern
Construct complex objects step by step — same construction code can produce different representations.
📌 Key IdeaSeparates construction of a complex object from its representation. Call
setX().setY().build() (or a director with steps) instead of telescoping constructors or giant parameter lists.Why It Matters
- Telescoping ctor killer — Replaces
new Pizza(size, cheese, sauce, ...)hell. - Readable at call site — Named methods document intent better than positional args.
- Validation in one place —
build()can enforce invariants before exposing the object.
Visual
🧱 Fluent chain → immutable product
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("/api"))
.header("Accept", "application/json")
.POST(BodyPublishers.ofString("{}"))
.build();Optional parameters accumulate; build() validates and returns an immutable (often) product.
When to Use
- Many optional fields or combinations — avoid 12-arg constructors.
- You want an immutable product after construction (
StringBuilder→String). - Construction has ordered steps or shared algorithms (Director).
- Same building process must create different representations (XML vs JSON export).
When NOT to Use
- Object is simple — a constructor or static factory suffices.
- You only choose which subclass to instantiate — that is Factory Method territory.
- Team overuses fluent APIs for everything — readability suffers.
Anti-Pattern (What NOT to Do)
Telescoping constructorBadjava
public Pizza(int size, boolean cheese, boolean pepperoni,
boolean olives, String crust, boolean extraSauce) {
// Callers pass false,false,false,... — unreadableEasy to swap two booleans; hard to extend.
The Right Way
Fluent builderGoodjava
Pizza p = new Pizza.Builder(12)
.cheese().pepperoni()
.crust(Crust.THIN)
.build();Each step returns
this (or a staged type); build() returns Pizza.Pros & Cons
👍 Pros
- Controls construction step by step; can defer
build()until valid. - Same director code can target different builders (e.g. HTML vs Markdown).
- Immutability-friendly — set fields only during build.
👎 Cons
- More boilerplate — builder mirrors product fields.
- Overkill for 2–3 simple parameters.
Common Confusions Cleared Up
Builder vs Factory Method
Factory Method picks which concrete class to instantiate in one shot. Builder assembles one instance with many optional pieces — often the class is fixed (HttpRequest).
Builder vs Abstract Factory
Abstract Factory creates families of distinct products. Builder focuses on configuring one complex product with a fluent or staged API.
Common Mistakes / Anti-Patterns
- Mutable product leaked before
build()completes. - Builder that allows illegal states until runtime.
Interview Q&A
Likely Follow-up Questions
- Staged builder (type-safe mandatory fields) — when would you use it?
- How does Lombok
@Buildermap to this pattern?
Quick Cheat Sheet
IntentStepwise assembly; optional parts; readable API.
JDK
StringBuilder, HttpRequest.newBuilder.vs FactoryFactory picks type; Builder fills one complex object.
DirectorOptional recipe over a builder interface.