My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more

The Builder Pattern in Node.js & Typescript

Itay Elgazar's photo
Itay Elgazar
·Jan 26, 2019

The Intent

Separate the construction of a complex object from its representation so that the same construction process can create different representations. -"Design Patterns, Elements of Reusable Object-Oriented Software"

Consider this piece of code:

const myHouse = new House('John Street 14', 4, true, true);

Assume that it's your first day at the job, you got a task to extend and add some properties to the House class. Would you understand what are all the arguments signs for? Let's say that the first argument is quite readable (the address of the house) but besides that, the second parameter, the third parameter, for me they mean nothing.

Well, here comes the Builder Pattern.

What is the Builder Pattern and what does it Solve?

The definition of Builder Pattern is a separation of the construction of a complex object from its representation. A Builder class builds the final object step by step. This way, the Builder is independent of other objects.

This code:

const myHouse = new House('John Street 14', 4, true, true);

Becomes to:

const myHouse = new HouseBuilder('John Street 14')
                     .setFloor(4)
                     .makeParking()
                     .makeGarden()
                     .build();

The Advantages of the 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.
  • Forcing immutability to the object once you are done with the creation of the object.

Implementing a HouseBuilder

Let's implement a simple builder by the example of a House. As I mentioned before, a House class contains the following properties:

  • address (string)
  • floorNumber (number)
  • isHavingParking (boolean)
  • isHavingGarden (boolean)

Let's do that.

Firstable, let's create "house.ts" file which contains the following code:

import { HouseBuilder } from './house-builder';

export class House {

    address: string;
    floorNumber: number;
    isHavingParking: boolean;
    isHavingGarden: boolean;

    constructor(houseBuilder: HouseBuilder) {
        this.address = houseBuilder.getAddress();
        this.floorNumber = houseBuilder.getFloorNumber();
        this.isHavingParking = houseBuilder.isHavingParking();
        this.isHavingGarden = houseBuilder.isHavingGarden();
    }
}

Notice that the house just accept the HouseBuilder as parameter, and pull the relevant data from the builder object.

Now, let's implement our HouseBuilder, let's create "house-builder.ts" file which contains the following code:

import { House } from './house';

export class HouseBuilder {

    private readonly address: string;
    private floorNumber: number = 0;
    private withParking: boolean = false;
    private withGarden: boolean = false;

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

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

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

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

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


    isHavingParking() {
        return this.withParking;
    }

    isHavingGarden() {
        return this.withGarden;
    }

    getAddress() {
        return this.address;
    }

    getFloorNumber() {
        return this.floorNumber;
    }

}

You may 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.

Well, now that we have House class and HouseBuilder class, it's time to create our builder instance and build our brand new house!

Create your own main file, I prefer to call it "app.ts", that contains the following code:

import { HouseBuilder } from './house-builder';

const myHouse = new HouseBuilder('Adder')
    .setFloor(5)
    .makeGarden()
    .makeParking()
    .build();

There you go! You've just built your brand new house object with your HouseBuilder.