How to implement and use Builder pattern in JS
Tags: javascript, beginners, designpatterns, builder
Published: 2020-07-29 03:36:57

---
title: How to implement and use Builder pattern in JS
published: true
description: 
tags: javascript, beginner, designpatterns, builder
cover_image: https://images.unsplash.com/photo-1583773193008-fd93fbc3fe12?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2858&q=80
---

There might be cases when an object contains too many details to be passed via a constructor, and that might be the case to use builder pattern, so that an object setup could be done gradually, thus taking the complex construction of an object into smaller pieces


Let's consider a `Car` type abstraction:

```javascript
class Car {
    brand;
    model;
}
```



At this point the encapsulation of these fields are not relevant, as it can be added; and also the set of properties is kept minimal for the ease of understanding, although the Builder pattern could make sense for a more complex type.



The builder pattern, as it's representation, should take values from external world, that will be injected into `Car` object, that will also be contained by the builder. When the object is considered to have everything set up, the build method should be called, which basically will return the built object.

The following is a possible implementation of the `Car` builder:



```javascript
class CarBuilder {
    #car;
    constructor(car = null) {
        this.#car = car || new Car();
    }

    madeBy(brand) {
        this.#car.brand = brand;
        return this;
    }

    model(model) {
        this.#car.model = model;
        return this;
    }

    build() {
        return this.#car;
    }
}
```



Note that in this implementation, the `Car` object could be also injected into builder, which makes the implementation of the builder less coupled with the `Car` object itself. And this is how it can be used:

```javascript
let carBuilder = new CarBuilder(new Car());
let car = carBuilder.madeBy("Toyota").model("Prius").build();

console.log(car) // => Car { brand: 'Toyota', model: 'Prius' }
```



This way, the model name and brand name was passed to a `Car` object, using `madeBy` and `model` method of a separate abstraction.



This implementation, can be replaced to a more functional approach:

```javascript
class FunctionalCarBuilder {
    actions = [];

    constructor(car) {
        this.car = car
    }

    madeBy(brand) {
        this.actions.push(function(car) {
            car.brand = brand;
        })
        return this;
    }

    model(model) {
        this.actions.push(function(car) {
            car.model = model;
        })
        return this
    }

    build() {
        for (let i = 0; i < this.actions.length; i++) {
            const build = this.actions[i];
            build(this.car)
        }
        return this.car
    }
}
```



which can be used as follows:




```javascript
let carBuilder = new FunctionalCarBuilder(new Car());
let car = carBuilder.madeBy("Toyota").model("Prius").build();

console.log(car) // => Car { brand: 'Toyota', model: 'Prius' }
```


So it does have the same interface, however here we have a set of function objects, that basically are modifiers of the build object. It might be useful for the cases when we need to decouple the logic of value definition from the builder, and don't have any assignment parameter. To go even further, a modifier function can be passed as parameter on specific builder methods, and this way to improve the decoupling.


### Conclusion

The builder pattern can be extremely useful when we have to deal with definition of an object with a complex structure, thus the object definition is delegated to separate abstraction, and the control of definition process is even better. Due to it's nature, JavaScript provides several ways of builder definitions; although the interface is the same, the approach and the mechanism of object construction would be different.