Design Pattern #7 – Builder Pattern

RMAG news

This article is the last one in our series on design patterns for frontend development. Throughout this series, we’ve looked at various patterns, like the Observer and PubSub pattern, that help developers write better code. The Builder Pattern, which we will talk about here, is another useful tool.

The Builder Pattern

The Builder Pattern is a creational design pattern that allows developers to construct complex objects step-by-step. It separates the construction of an object from its representation, enabling the same construction process to create different representations.

In JavaScript, this pattern is particularly useful when dealing with objects that require numerous optional parameters or when the construction process involves several steps. By using the Builder Pattern, developers can create more readable and maintainable code by chaining method calls to set properties and ultimately build the desired object in a controlled manner.

Real case scenario

Imagine a frontend developer tasked with creating a complex dashboard for a web application. The challenge is to allow users to customize their dashboard with various widgets such as charts, tables, and notifications. Each widget needs different settings such as data sources, display options, and refresh intervals. Managing all these options through a single constructor or multiple setters can become cumbersome and prone to mistakes.

The Builder Pattern provides an elegant solution by using a DashboardBuilder class, developers can chain method calls to set properties for each widget, ensuring that all necessary configurations are applied before the dashboard is built. This approach not only makes the code more readable and maintainable but also allows for flexibility in creating different types of dashboards with varying complexities.

Hands on

The code below exemplifies the discussed scenario. It shows how a frontend developer can use the Builder Pattern to create a this dashboard:

class DashboardBuilder {
constructor() {
this.widgets = [];
}

addChart(type, data) {
this.widgets.push({ type: chart, chartType: type, data });
return this;
}

addTable(data) {
this.widgets.push({ type: table, data });
return this;
}

addNotification(message) {
this.widgets.push({ type: notification, message });
return this;
}

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

class Dashboard {
constructor(builder) {
this.widgets = builder.widgets;
}

render() {
this.widgets.forEach(widget => {
switch (widget.type) {
case chart:
console.log(`Rendering a ${widget.chartType} chart with data:`, widget.data);
break;
case table:
console.log(Rendering a table with data:, widget.data);
break;
case notification:
console.log(Showing notification:, widget.message);
break;
default:
console.log(Unknown widget type);
}
});
}
}

// Usage
const dashboard = new DashboardBuilder()
.addChart(line, [1, 2, 3])
.addTable({ header: [Name, Age], rows: [[Alice, 30], [Bob, 25]] })
.addNotification(Welcome to your dashboard!)
.build();

dashboard.render();

This code demonstrates the implementation of the Builder Pattern for creating a customizable dashboard. Here’s a breakdown of the main components:

1. DashboardBuilder class:

Manages the construction of the dashboard
Has methods to add different types of widgets (charts, tables, notifications)
Each method returns this to allow method chaining
The build() method creates and returns a new Dashboard instance

2. Dashboard class:

Represents the final product
Takes a DashboardBuilder instance in its constructor
Has a render() method to display the widgets

3. Usage example:

Creates a new dashboard with a line chart, a table, and a notification
Uses method chaining to add widgets in a readable manner
Calls build() to create the Dashboard instance
Finally, calls render() to display the dashboard

This pattern allows for flexible and readable creation of complex dashboard objects with various widgets and configurations.

Overall, the Builder Pattern is a powerful tool in software development, especially when dealing with complex object creation scenarios. It promotes cleaner code, reduces the likelihood of errors, and enhances the maintainability of the codebase.

If you have any questions feel free to drop a comment below. Also, make sure to check out the other articles in our frontend design patterns series!

Please follow and like us:
Pin Share