Builder Pattern: Step-by-Step Construction of Complex Objects
design-patternscreationalbuilder

Intent
The Builder pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations. It's especially useful when an object has many optional parameters.
The Problem
Have you seen constructors like this?
// Telescopic constructor - hard to use and maintain
const user = new User(
'John',
'Doe',
'[email protected]',
true,
false,
'premium',
null,
'dark',
['es', 'en']
);Without looking at documentation, what does each parameter mean? What if you only want to set the theme without modifying the plan?
The Solution: Builder
const user = new UserBuilder()
.withName('John', 'Doe')
.withEmail('[email protected]')
.asVerified()
.withPlan('premium')
.withTheme('dark')
.withLanguages(['es', 'en'])
.build();Each method is self-documenting. You only set what you need.
Diagram
classDiagram
class Builder {
<<interface>>
+setPartA()
+setPartB()
+build(): Product
}
class ConcreteBuilder {
-product: Product
+setPartA()
+setPartB()
+build(): Product
}
class Director {
-builder: Builder
+construct()
}
class Product {
+partA
+partB
}
Builder <|.. ConcreteBuilder
Director --> Builder
ConcreteBuilder --> ProductTypeScript Implementation
// Product: HTTP Request
interface HttpRequest {
method: string;
url: string;
headers: Record<string, string>;
body?: unknown;
timeout: number;
retries: number;
}
// Builder with fluent API
class HttpRequestBuilder {
private request: Partial<HttpRequest> = {
headers: {},
timeout: 30000,
retries: 0,
};
get(url: string): this {
this.request.method = 'GET';
this.request.url = url;
return this;
}
post(url: string): this {
this.request.method = 'POST';
this.request.url = url;
return this;
}
withHeader(key: string, value: string): this {
this.request.headers![key] = value;
return this;
}
withAuth(token: string): this {
return this.withHeader('Authorization', `Bearer ${token}`);
}
withBody(body: unknown): this {
this.request.body = body;
return this.withHeader('Content-Type', 'application/json');
}
build(): HttpRequest {
if (!this.request.method || !this.request.url) {
throw new Error('Method and URL are required');
}
return this.request as HttpRequest;
}
}When to Use
| Situation | Recommendation |
|---|---|
| Object with many optional parameters | ✅ Recommended |
| Complex configurations | ✅ Recommended |
| Step-by-step construction with validation | ✅ Recommended |
| Simple object with few parameters | ❌ Overkill |
Conclusion
The Builder pattern is your best ally for building complex objects in a readable and maintainable way.