JavaScript Design Patterns - Builder
Tags: javascript, webdev, codenewbie, beginners
Published: 2021-06-12 10:14:19

Builder is one of the Creational Design Patterns, which help you deal with how objects are created. You should pay close attention to your object creation techniques that may morph into serious design problems if you neglect them.

[Start here if you're just getting started with Design Patterns in JavaScript](https://learn.coderslang.com/0075-getting-started-with-javascript-design-patterns/)

## Real-world examples

Picture having to assemble tiny lego pieces into what looks like a house. There are several different ways of grouping them into various representations.

A basic house will have a door, zero or more windows, and a roof with surrounding walls. Some may even have a garage, and some have a swimming pool. We'd wish for the process to be simpler and flexible to accommodate changes.

A step-by-step assembly of the lego pieces at your disposal forms the essence of the Builder pattern.

Objects are thus constructed following a sequence of steps one after the other instead of arriving at it all at once.

JavaScript objects are a collection of properties and methods. Properties are fields or variables associated with the object. And methods are functions that you're going to invoke to manipulate the fields. Objects' properties are closely related to each other, at least semantically in the worst case.

JavaScript provides many ways to create objects.

## Object Initializer

The most common method of creating an object in JavaScript is an `object literal` notation.

```jsx
const employee = {
  firstName: 'Sam',
  lastName: 'Greene',
  id: '12340987',
  phone: '07123456789'
};
```

where `firstName`, `lastName`, `id` and `phone` are properties of the object named `employee`.

## Constructor

Alternatively, we can use a constructor to create multiple instances of similar objects using the `new` keyword.

```jsx
class Employee {
	constructor(fname, lname, id, ph) {
	  this.firstName = fname;
    this.lastName = lname;
    this.id = id;
    this.ph;
  }
};

const employee1 = new Employee('Sam', 'Greene', 12340987, '07123456789');
const employee2 = new Employee('Nate', 'Tyson', 56478390, '07987654321');
```

## Using Object.create

`Object.create()` is an inbuilt function that you can use to create multiple instances of an object. It allows you to pass in the template object as an input, thus choosing the prototype for the objects as desired, without a constructor.

```jsx
const Employee = {
  isAdmin: false,
  getRole: function() {
	  return this.isAdmin ? 'Admin' : 'RegularEmp';
  };
};

const emp1 = Object.create(Employee);
emp1.getRole(); //'RegularEmp'

const emp2 = Object.create(Employee);
emp2.isAdmin = true;
emp2.getRole(); //'Admin'
```

In this example, both `emp1` and `emp2` inherited the method `getRole`. Once you've set the `isAdmin` to `true`, the role of `emp2` changed to `Admin`.

## The problem

So it looks like there's already a bunch of ways to create objects in JavaScript. Why would we want to invent something different?

Let's consider two important questions:

- What if you need to create a complex object comprising too many fields and properties?
- What if you need to create multiple instances of almost the same object?

Object literal is not a good choice for it doesn't help with code reusability. Every time you need a new object, you'd have to list all its fields over and over.

Constructor would solve the issue to a certain extent, but it'd be cumbersome. You'd have to remember the inputs to it, some of which are mandatory and others aren't.

## **The Builder Pattern**

What if you had a way to address just the above two problems while hiding the internal representation from anyone using it?

Objects are all around us in real life. And you can compare JavaScript objects with them.

A car, for example, comes in different colors or with a different number of seats. A house can have a various number of doors, windows, and chimneys. Differences are everywhere, yet there are some similarities.

The Builder Pattern gives you a way to simplify creating a complex object by separating it from its representation.

This pattern eases the construction of an object, taking the process through a step-by-step progression while also encapsulating (hiding) the implementation details of these steps.

Let's look into what a flexible design looks like for a simple OTG builder and how it evolves with the help of the Builder pattern.

## Building an OTG using the Builder Design Pattern

There should be provision to build OTGs in various colors, models, pricing, and features. Some are built to support high temperature and a good timer selection span. For example, lower-end models come with low-temperature settings and a default timer.

### Step 1: Class OTG

A simple class for OTG here has a JS constructor that takes in four parameters. Every OTG instance has a default title, an overridable temperature, and time selections which are by default set to 150 and 30 respectively.

```jsx
class OTG {
	constructor(model, color, maxTemperature, maxTimeSelection) {
	  this.model = model;
	  this.title = 'OTG';
	  this.color = color;
	  this.maxTemperature = maxTemperature || 150;
	  this.maxTimeSelection = maxTimeSelection || 30;
	}
}

const redOTG = new OTG('LG', 'red');
const highTempOTG = new OTG('LG', 'black', 200);
const highendTimeOTG = new OTG('LG', 'red', '150', '60');
```

The above code looks ok for now. But there's a problem with it.

Imagine having to create multiple selections of OTG instances. It will get difficult to keep track of the parameters and their order in the constructor. Also, at times, there will be no need for sending in certain optional parameters.

### Step 2: Create a builder class

Let's look at how we can avoid cramming the constructor to accept minimal parameters.

```jsx
class OTGBuilder {
  constructor(model, color) {
    this.model = model;
    this.title = 'OTG';
    this.color = color;
  }
}
```

OTGBuilder class here is responsible for the creation of instances of the OTG class. But it doesn't do this yet. For now, it just captures the basic fields model and color.

These fields are a must, so we include them directly in the constructor.

### Step 3: Add optional parameters as separate functions

You've probably noticed that the fields `maxTemperature` and `maxTimeSelection` can't be configured with a the constructor.

These properties are optional and we'll create separate functions to set them.

```jsx
class OTGBuilder {
  constructor(model, color) {
	  this.model = model;
    this.title = 'OTG';
    this.color = color;
  }
  setMaxTemperature(temp) {
    this.maxTemperature = temp;
    return this;
  }

  setMaxTimeSelection(maxTime) {
    this.maxTimeSelection = maxTime;
    return this;
  }
}
```

It's necessary to add `return this;` to make sure we can use chained call when we're working with the Builder Design Pattern.

```jsx
const otg = new OTGBuilder('MorphyRichards', 'Black')
.setMaxTemperature(250)
.setMaxTimeSelection(60);
```

### Step 4: Build

The only remaining problem is that the object `otg` isn't the proper OTG yet. It's an instance of the `OTGBuilder` class. And you need to implement the last step of the process, which is the `build()` method.

```jsx
class OTGBuilder {
  constructor(model, color) {
    this.model = model;
    this.title = 'OTG';
    this.color = color;
  }
  setMaxTemperature(temp) {
    this.maxTemperature = temp;
    return this;
  }

  setMaxTimeSelection(maxTime) {
    this.maxTimeSelection = maxTime;
    return this;
  }

  build() {
    return new OTG(this.model, this.color,
    this.maxTemperature, this.maxTimeSelection);
  }
}
```

Now, you can call the `build()` method when you're ready to create your OTG.

```jsx
const basicOTG = new OTGBuilder('MorphyRichards', 'Black')
  .setMaxTemperature(250)
  .setMaxTimeSelection(60)
  .build();
```

If you want to, you can always skip the steps to set optional parameters.

```jsx
const default = new OTGBuilder('Generic OTG', 'White')
  .build();
```

The properties `maxTemperature` and `maxTimeSelection` will default to 150 and 30 unless you overwrite them with `setMaxTemperature` and `setMaxTimeSelection`.

## Thanks for reading!

I hope you liked this intro the Builder Design Pattern. Like/share/comment if you want me to cover more JavaScript Design Patterns in the future.

Get my [free e-book](https://learn.coderslang.com/free-ebooks/) to prepare for the technical interview or start to [Learn Full-Stack JavaScript](https://js.coderslang.com)