Builder Pattern

What Is It?
Why Use It?
- When an object has many optional fields or configurations
- To avoid huge constructors or subclass explosion
- When you want to build different representations of the same object (e.g., a car and its user manual)
Real-World Analogy
- Build walls
- Add doors and windows
- Install the roof
TypeScript Example – Building a Car
Ts
// Product: Car
class Car {
seats?: number;
engine?: string;
tripComputer?: boolean;
gps?: boolean;
show(): void {
console.log(this);
}
}
// Builder Interface
interface Builder {
reset(): void;
setSeats(count: number): void;
setEngine(engine: string): void;
setTripComputer(hasComputer: boolean): void;
setGPS(hasGPS: boolean): void;
}
// Concrete Builder: builds a car
class CarBuilder implements Builder {
private car: Car;
constructor() {
this.car = new Car();
}
reset(): void {
this.car = new Car();
}
setSeats(count: number): void {
this.car.seats = count;
}
setEngine(engine: string): void {
this.car.engine = engine;
}
setTripComputer(hasComputer: boolean): void {
this.car.tripComputer = hasComputer;
}
setGPS(hasGPS: boolean): void {
this.car.gps = hasGPS;
}
getResult(): Car {
const result = this.car;
this.reset(); // ready for next build
return result;
}
}
// Director: knows how to build specific car types
class Director {
constructor(private builder: Builder) {}
constructSportsCar(): void {
this.builder.reset();
this.builder.setSeats(2);
this.builder.setEngine("Sport Engine");
this.builder.setTripComputer(true);
this.builder.setGPS(true);
}
constructSUV(): void {
this.builder.reset();
this.builder.setSeats(5);
this.builder.setEngine("SUV Engine");
this.builder.setTripComputer(true);
this.builder.setGPS(false);
}
}
// Client Code
const carBuilder = new CarBuilder();
const director = new Director(carBuilder);
director.constructSportsCar();
const sportsCar = carBuilder.getResult();
sportsCar.show();
director.constructSUV();
const suv = carBuilder.getResult();
suv.show();
Output:
Ts
Car { seats: 2, engine: 'Sport Engine', tripComputer: true, gps: true }
Car { seats: 5, engine: 'SUV Engine', tripComputer: true, gps: false }
When to Use Builder
- You have a class with lots of optional parameters.
- You need to build different representations (e.g., objects vs. manuals).
- You want to reuse construction logic but keep object types separate.
Pros & Cons
- Build objects step-by-step with optional parts
- Reuse the same steps to build different products
- Isolate complex logic into builder classes
- Enforces the Single Responsibility Principle
- Adds extra classes and interfaces
- Can be overkill for simple objects