Builder Pattern

  • Sprouting
  • c.

The builder pattern is a creational design pattern for creating variations of objects step-by-step.

Example

Real-world analogy: a housing construction project

design-patterns/src/creational/builder.ts at main

Products

Houses can have different configurations, which require different variations of products.

type Blueprint = string;
class Building {
house: boolean;
garage: boolean;
garden: boolean;
pool: boolean;
statues: number;
constructor() {
this.house = false;
this.garage = false;
this.garden = false;
this.pool = false;
this.statues = 0;
}
}

Builder

An architect can draw blueprints from the given requirments. Likewise, an engineer can build from the given requirements. Both are experts in housing construction, but produce different things; the architect draws a houseโ€™s blueprint, the engineer builds it.

interface ConstructionExpert {
setHouse(): void;
setWithGarage(): void;
setWithGarden(): void;
setWithPool(): void;
setWithStatues(statues: number): void;
}
class Architect implements ConstructionExpert {
private blueprint: Blueprint;
constructor() {
this.blueprint = "";
}
private reset() {
this.blueprint = "";
}
setHouse() {
this.blueprint += "๐Ÿ ";
}
setWithGarage() {
this.blueprint += " + ๐Ÿš˜";
}
setWithGarden() {
this.blueprint += " + ๐ŸŒป";
}
setWithPool() {
this.blueprint += " + ๐ŸŠ";
}
setWithStatues(statues: number) {
for (let i = 0; i < statues; i++) {
this.blueprint += " + ๐Ÿ—ฟ";
}
}
getResult(): Blueprint {
const result = this.blueprint;
this.reset();
return result;
}
}
class Engineer implements ConstructionExpert {
private building: Building;
constructor() {
this.building = new Building();
}
private reset() {
this.building = new Building();
}
setHouse() {
this.building.house = true;
}
setWithGarage() {
this.building.garage = true;
}
setWithGarden() {
this.building.garden = true;
}
setWithPool() {
this.building.pool = true;
}
setWithStatues(statues: number) {
this.building.statues = statues;
}
getResult(): Building {
const result = this.building;
this.reset();
return result;
}
}

Director

The project manager directs the experts to create their respective products. The director knows about the variations of houses, but doesnโ€™t know how to create the products needed for those variations.

class ProjectManager {
private expert: ConstructionExpert;
constructor(Expert: ConstructionExpert) {
this.expert = Expert;
}
setExpert(expert: ConstructionExpert) {
this.expert = expert;
}
simpleHouse() {
this.expert.setHouse();
}
houseWithGarage() {
this.simpleHouse();
this.expert.setWithGarage();
}
houseWithGarden() {
this.simpleHouse();
this.expert.setWithGarden();
}
houseWithPool() {
this.simpleHouse();
this.expert.setWithPool();
}
houseWithStatues(statues: number) {
this.simpleHouse();
this.expert.setWithStatues(statues);
}
}

Client

When the project manager wants a blueprint for a particular variation of house, they call upon an architect. When they want the building, they call upon an engineer. Calling the getResult method of the architect returns a Blueprint based on the step-by-step instructions given by the project manager. Calling the getResult method on the engineer returns a Building based on the step-by-step instructions given by the project manager.

const architect = new Architect();
const projectManager = new ProjectManager(architect);
projectManager.simpleHouse();
let blueprint = architect.getResult();
console.log(blueprint);
// Expected output:
// ๐Ÿ 
projectManager.houseWithStatues(3);
blueprint = architect.getResult();
console.log(blueprint);
// Expected output:
// ๐Ÿ  + ๐Ÿ—ฟ + ๐Ÿ—ฟ + ๐Ÿ—ฟ
const engineer = new Engineer();
projectManager.setExpert(engineer);
projectManager.simpleHouse();
let building = engineer.getResult();
console.log(building);
// Expected output:
// Building {
// house: true,
// garage: false,
// garden: false,
// pool: false,
// statues: 0
// }
projectManager.houseWithGarden();
building = engineer.getResult();
console.log(building);
// Expected output:
// Building {
// house: true,
// garage: false,
// garden: true,
// pool: false,
// statues: 0
// }

Backlinks