TypeScript Builder Pattern Example

This post shows how to use the Builder Pattern in TypeScript with an example.
The definition of the Builder Pattern is a separation of the construction of a complex object from its representation.

Problem Statement

Let's look at below code, there are many parameters in the constructor and it's a complex object.
export class House {
    address: string;
    floorNumber: number;
    city: string;
    isHavingParking: boolean;
    isHavingGarden: boolean;

    constructor(address: string, floorNumber: number, city: string, isHavingParking: boolean, isHavingGarden: boolean){
        this.address = address;
        this.floorNumber = floorNumber;
        this.city = city;
        this.isHavingParking = isHavingParking;
        this.isHavingGarden = isHavingGarden;
    }
}

function clientCode() {
    const myHouse = new House("Ramesh Fadatare 4803111", 14, "Pune", true, true);    
}

clientCode();
Let's solve the above problem using a builder pattern.

TypeScript Builder Pattern

Let's use Builder Pattern, the parameters in the constructor are reduced and served in a much more readable way, and thus there is no need to pass in null for optional parameters to the constructor.
Let’s create “builder.ts” file which contains the following code:
/**
 * The definition of the Builder Pattern is a separation of the 
 * construction of a complex object from its representation.
 * 
 */
export class House {
    address: string;
    floorNumber: number;
    city: string;
    isHavingParking: boolean;
    isHavingGarden: boolean;
    
    constructor(houseBuilder: HouseBuilder) {
        this.address = houseBuilder.address;
        this.city = houseBuilder.city;
        this.floorNumber = houseBuilder.floorNumber;
        this.isHavingParking = houseBuilder.isHavingParking;
        this.isHavingGarden = houseBuilder.isHavingGarden;
    }
}

/**
 * HouseBuilder implementation
 */
export class HouseBuilder {

    private readonly _address: string;
    private _floorNumber: number = 0;
    private _isHavingParking: boolean = false;
    private _city: string;
    private _isHavingGarden: boolean = false;

    constructor(address: string) {
        this._address = address;
    }

    setFloor(floor: number) {
        this._floorNumber = floor;
        return this;
    }

    setCity(city: string){
        this._city = city;
        return this;
    }

    makeParking() {
        this._isHavingParking = true;
        return this;
    }

    makeGarden() {
        this._isHavingGarden = true;
        return this;
    }

    build() {
        return new House(this);
    }

    get isHavingParking() {
        return this._isHavingParking;
    }

    get isHavingGarden() {
        return this._isHavingGarden;
    }

    get address() {
        return this._address;
    }

    get floorNumber() {
        return this._floorNumber;
    }

    get city(){
        return this._city;
    }
}

function clientCode() {
    const myHouse = new HouseBuilder('Ramesh Fadatare, Street: Katraj')
    .setCity("Pune")
    .setFloor(5)
    .makeGarden()
    .makeParking()
    .build();

    console.log(myHouse);
}

clientCode();
Notice that we always return this in every function (expect build). Well, this because we want to “chain” everything together, and then build and return the new house instance according to the builder state.
Run:
  1. Compile the above code using the TypeScript compiler.
  2. Above code is compiled to plan JavaScript code
  3. Run Javascript code using node
C:\typescript-design-patterns\builder> tsc .\builder.ts
C:\typescript-design-patterns\builder> node .\builder.js
Output:
House {
  address: 'Ramesh Fadatare, Street: Katraj',
  city: 'Pune',
  floorNumber: 5,
  isHavingParking: true,
  isHavingGarden: true }

Comments