Unravel › Java concepts › Design patterns and architecture
Builder pattern
A builder creates a complex object step by step with readable, named steps (Pizza.builder().size(12).cheese(true).build()), instead of one constructor with many positional parameters.
Learn these first
At a glance
Ordering at a sandwich counter: you say each choice in turn, in any order, and only at the end they put it together and hand it over.
- 1A nested static Builder class holds the fields with setter-like methods that return this, so calls chain: .name("x").qty(2)build() validates and creates the final object.
- 2The target class gets a private constructor taking the builder, so objects can only come from the builder and can be immutable
- 3Lombok @Builder generates all that; the JDK itself uses builders in HttpRequest.newBuilder(), Stream.builder(), ProcessBuilder, Locale.Builder
- 4Use it when there are many optional parameters, or when the object must be valid and immutable once built
- Put validation in build() (required fields, combinations) so an invalid object can never exist
- Compare alternatives: a record for few fields, static factory methods for named constructors, and the "telescoping constructor" anti-pattern that the builder avoids
- A builder is plain Java: just an object that collects values
public class Pizza { private final int size; private final boolean cheese; private Pizza(Builder b) { this.size = b.size; this.cheese = b.cheese; } public static Builder builder() { return new Builder(); } public static class Builder { private int size = 12; private boolean cheese; public Builder size(int size) { this.size = size; return this; } public Builder cheese(boolean cheese) { this.cheese = cheese; return this; } public Pizza build() { if (size <= 0) throw new IllegalStateException("size must be positive"); return new Pizza(this); } }}- line 3 uses Builder, the core of Builder pattern
- line 4 uses Builder, the core of Builder pattern
- line 5 uses Builder, the core of Builder pattern
- line 7 uses Builder, the core of Builder pattern
- line 8 uses Builder, the core of Builder pattern
- line 9 uses build, the core of Builder pattern
Read the full explanation (about 1 min)
A builder creates a complex object step by step with readable, named steps (Pizza.builder().size(12).cheese(true).build()), instead of one constructor with many positional parameters.
A mental model
Ordering at a sandwich counter: you say each choice in turn, in any order, and only at the end they put it together and hand it over.
How it works
A nested static Builder class holds the fields with setter-like methods that return this, so calls chain: .name("x").qty(2). build() validates and creates the final object.
The target class gets a private constructor taking the builder, so objects can only come from the builder and can be immutable.
Lombok @Builder generates all that; the JDK itself uses builders in HttpRequest.newBuilder(), Stream.builder(), ProcessBuilder, Locale.Builder.
Use it when there are many optional parameters, or when the object must be valid and immutable once built.
Going deeper
Put validation in build() (required fields, combinations) so an invalid object can never exist. Make the builder itself not thread safe and short lived.
Compare alternatives: a record for few fields, static factory methods for named constructors, and the "telescoping constructor" anti-pattern that the builder avoids.
A copy builder (toBuilder()) is the idiomatic way to create a modified copy of an immutable object.
Under the hood
A builder is plain Java: just an object that collects values. The returned this enables the "fluent interface". Each chained call is a normal method call; the JIT usually inlines them so the cost disappears.
Common mistakes
- Skipping validation in
build(). - Reusing a builder after
build()and sharing mutable state between products. - Writing a builder for a class with two fields.
How Unravel recognises it
When you paste code, Unravel looks for these signs of builder pattern. Spotting them yourself is a good habit when you read unfamiliar code:
- Annotations:
@SuperBuilder@Builder - Method calls:
newBuilder()build() - Method names you declare:
builder()build()
Part of a learning path
- Design patterns and SOLID · previous: Singleton pattern · next: Factory pattern
Related concepts
Frequently asked questions
What is Builder pattern?
A builder creates a complex object step by step with readable, named steps (Pizza.builder().size(12).cheese(true).build()), instead of one constructor with many positional parameters.
What are the most common mistakes with Builder pattern?
Skipping validation in build(). Reusing a builder after build() and sharing mutable state between products. Writing a builder for a class with two fields.
How can I see Builder pattern in real code?
Paste your own Java into Unravel and it will point out where builder pattern appears, explain how it works at the detail level you choose, and draw the flow of the code around it.