Builder Pattern
- Pronunciation
- BIL-der PAT-urn
In short
The builder pattern builds a complex object step by step through a separate builder object, with named steps instead of a long constructor full of arguments.
What is the builder pattern?
Constructors become hard to use when an object has many options. new HttpRequest("GET", url, null, 30, true, false, headers) is unreadable, and adding a constructor for every combination, the telescoping constructor problem, makes it worse. A builder lets you set only what you need, by name, and then create the object: HttpRequest.builder().url(url).timeout(30).header("Accept", "json").build().
The builder collects the settings, applies defaults and validates the combination before creating the final object, often an immutable one. That means the object is never seen in a half-configured state, and rules such as "a POST request needs a body" can be checked in one place, inside build().
It is one of the original Gang of Four creational patterns from 1994 and is especially common in Java and C#, where Lombok's @Builder or code generators remove the boilerplate. Test data builders use the same idea to create objects with sensible defaults and override only what a test cares about. Query builders, such as those in ORMs, and Java's StringBuilder follow the step-by-step style too.
A common misconception is that every class needs a builder. In languages with named and default parameters, such as Python, Kotlin, C# and JavaScript with options objects, a plain constructor is often just as clear. Builders pay off for objects with many optional parts, complex validation or a need for immutability.
Key takeaways
- A builder creates complex objects step by step with named settings.
- It solves the telescoping constructor problem.
- build() applies defaults and validates before creating the object.
- It is common in Java and C#, often generated with tools like Lombok.
- Named and default parameters often make it unnecessary.
Example
public final class Email {
private final String to, subject, body;
private final List<String> cc;
private Email(Builder b) { to = b.to; subject = b.subject; body = b.body; cc = List.copyOf(b.cc); }
public static Builder builder() { return new Builder(); }
public static final class Builder {
private String to, subject = "(no subject)", body = "";
private final List<String> cc = new ArrayList<>();
public Builder to(String v) { to = v; return this; }
public Builder subject(String v) { subject = v; return this; }
public Builder body(String v) { body = v; return this; }
public Builder cc(String v) { cc.add(v); return this; }
public Email build() {
if (to == null) throw new IllegalStateException("Recipient is required");
return new Email(this); // immutable, never half-configured
}
}
}
Email email = Email.builder().to("ada@example.com").subject("Welcome").cc("team@example.com").build();Readers ask
When should I use the builder pattern?
When an object has many optional parameters, needs validation across several fields, or should be immutable once created. For objects with a few required fields, a constructor is simpler.
What is the difference between the builder and factory patterns?
A factory decides which object to create and returns it in one call. A builder focuses on configuring one complex object through several steps before creating it.
What is a fluent interface?
An API where each method returns the object itself, so calls can be chained into a readable sentence, such as builder.to(...).subject(...).build(). Builders are usually written this way.
See also
- Design PatternSoftware Architecture, p. 13A design pattern is a proven, reusable solution to a common problem in software design, described as a general template rather than as finished code.
- Factory PatternSoftware Architecture, p. 19The factory pattern is a creational design pattern that moves object creation into a dedicated function or class, so callers never name the concrete class.
- ImmutabilityProgramming Fundamentals, p. 27Immutability means a value cannot be changed after it is created, so every update produces a new value instead of modifying the original in place.
- Singleton PatternSoftware Architecture, p. 41The singleton pattern is a creational design pattern that ensures a class has only one instance and provides a single, global point of access to it.
- ClassProgramming Fundamentals, p. 9A class is a blueprint in object-oriented programming that defines the data and behavior shared by a group of objects, which are created from it as instances.
- ObjectProgramming Fundamentals, p. 39An object is a bundle of related data and behavior: values in named fields, often called properties, and functions that work on them, called methods.
Spotted a mistake or something missing on this page?Suggest an edit