Skip to main content

Command Palette

Search for a command to run...

Advent Calendar #3 - The builder pattern

Published
2 min readView as Markdown
A

Software developer and CEO at RoyalZSoftware. I build web applications for startups with Ruby on Rails, Angular and React.

You've used it and I think you were as impressed as me, the first time you've seen it. This post is about the builder pattern and I want you to know how to implement it.

What is the builder pattern

The builder pattern is a creational pattern and is used to create objects, that have large constructors, with ease.

Imagine you have a Car model that requires a lot of parameters.

class Car {
    constructor(public name: string, public brand: string, public numberOfDoors: number = 4, public color: string = 'red') {
    }
}

Lets now imagine creating a model

const hyundaiITwenty = new Car("I20", "Hyundai", undefined, "blue");

I left the numberOfDoors to undefined, because I want it to take the default. Do you see an issue alrady?

The problem might not be obvious with just four parameters. But what if the Car has 14 parameters? You're most likely to leave a lot of them undefined.

That's where the builder pattern comes in handy. With it you can just override certain fields.

class CarBuilder {
    public numberOfDoors = 4;
    public color = 'red';
    public brand: string;
    public name: string;

    public withColor(color: string): this {
        this.color = color;
        return this;
    }

    public withNumberOfDoors(noDoors: number): this {
        this.numberOfDoors = noDoors;
        return this;
    }

    public build(name: string, brand: string /*required parameters without default*/): Car {
        return new Car(name, brand, this.numberOfDoors, this.color);
    }
}

With this CarBuilder we can use following call chain

const car = new CarBuilder().withColor('blue').withNumberOfDoors(2).build("911", "Porsche");

A note on encapsulation

You should make the constructor of the actual Car object private. The CarBuildershould be the only class that can create a Carobject.

In most languages this is done by utilising nested classes. In Typescript, although it's not that obvious, this is possible too.

class Car {
    // truncated
    static CarBuilder = class {
        // truncated
    };

    private constructor(/*truncated*/) {

    }
}

// Usage
Car.CarBuilder.build(); // works

Conclusion

It's useful to know this pattern, especially with objects that have gigantic constructors. Subscribe to the RoyalZSoftware newsletter.

More from this blog

R

RoyalZSoftware

76 posts

This blog is about software development best practices and insights from RoyalZSoftware. Read it to advance your coding journey or to understand what we are doing for your software project.