Pattern - Builder
Published: 2023-01-13 20:54:05


![Pattern builder](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/npvht6l7rflnbw6z01ej.png)

The _Builder_ pattern was originally described by Gamma et al. in his book "Design Patterns: Elements of Reusable Object-Oriented Software" (1994). In it, the authors present the _Builder_ pattern as a way to separate the construction of a complex object from its representation, so that the same construction process can create different representations.

The _Builder_ pattern is a build pattern that focuses on separating the construction of a complex object from its representation, so that the same build process can create different representations. It lets you build objects step by step, adding different parts or characteristics to them over time.

In general, _Builder_ is used when you want to create complex objects that have many different parts or configurations and that are built through several steps. _Builder_ provides an interface for specifying these steps and adding the appropriate parts or characteristics to the object.

There are two main parts involved in the _Builder_ pattern, which are:

- **The Builder**: which is an interface to specify the steps to create the complex object. It defines the methods for adding the different parts or characteristics of the object.
- **The Director**: which is the object that controls the build process using the specified _Builder_. He can create many different types of objects using the same sequence of steps, but with different parts or characteristics.

There are several advantages to using the _Builder_ pattern in your code, which are:

- **Encapsulation**: The _Builder_ pattern allows you to hide the construction logic of a complex object inside _Builder_ and the Director, instead of exposing it directly to the client. This makes the code easier to understand and maintain.
- **Flexibility**: The _Builder_ pattern allows you to create different representations of a complex object using the same sequence of steps. This means you can create new representations without affecting existing code.
- **Reusability**: The _Builder_ pattern allows you to reuse the construction logic of a complex object in different contexts. This means that you can build similar objects using the same building logic.
- **Clarity**: the _Builder_ pattern makes the code clearer and more organized, as it separates the construction logic from the system logic. This means that you can easily understand how an object is constructed and how it is used.
- **Simplicity**: The _Builder_ pattern simplifies building complex objects by providing an organized way to add different parts or characteristics to an object over time.
- **Clean code**: By dividing the construction of a complex object into steps, it can make the code cleaner and easier to maintain as each step is isolated and easier to understand.

Below is a simple code example using the _Builder_ pattern.


```js
class SandwichBuilder {
    constructor() {
        this.sandwich = new Sandwich();
    }
    
    addBread() {
        this.sandwich.hasBread = true;
    }
    
    addCheese() {
        this.sandwich.hasCheese = true;
    }
    
    addLettuce() {
        this.sandwich.hasLettuce = true;
    }
    
    addMeat() {
        this.sandwich.hasMeat = true;
    }
    
    getSandwich() {
        return this.sandwich;
    }
}

class Sandwich {
    constructor() {
        this.hasBread = false;
        this.hasCheese = false;
        this.hasLettuce = false;
        this.hasMeat = false;
    }
}

class SandwichMaker {
    constructor() {
        this.builder = null;
    }
    
    setBuilder(builder) {
        this.builder = builder;
    }
    
    makeSandwich() {
        this.builder.addBread();
        this.builder.addCheese();
        this.builder.addLettuce();
        this.builder.addMeat();
    }
}

const sandwichBuilder = new SandwichBuilder();
const sandwichMaker = new SandwichMaker();

sandwichMaker.setBuilder(sandwichBuilder);
sandwichMaker.makeSandwich();

const mySandwich = sandwichBuilder.getSandwich();
console.log(mySandwich); 

```

The _SandwichBuilder_ class is responsible for building an instance of the _Sandwich_ class by adding different parts. It has methods for adding bread, cheese, lettuce, and meat, and a "getSandwich" method that returns the constructed sandwich object.

The _Sandwich_ class is a template class that represents the sandwich object. The constructor initializes the object with all its attributes as false, and the sandwichBuilder's addition methods will change the values.

The _SandwichMaker_ class is responsible for using the _SandwichBuilder_ object and making the sandwich, it is an object that controls the construction process using the specified Builder. The class has a method to set a Builder _(sandwichBuilder)_ and another method to make the sandwich(makeSandwich).

Finally we start a new instance of the _SandwichBuilder_ class called _sandwichBuilder_. Next, we create a new instance of the _SandwichMaker_ class called _sandwichMaker_.

After that, we configure the _sandwichMaker_ to use the _sandwichBuilder_ specified with the _setBuilder(sandwichBuilder)_ method. This means that the _SandwichMaker_ class will use the _sandwichBuilder_ to build the sandwich.

Finally, we use the _makeSandwich()_ method of the _sandwichMaker_ to build the sandwich and store the result in the _mySandwich_ variable. Finally, we use the console.log to print the constructed sandwich to the screen. The result would be a sandwich object with all its attributes set to true.

_Simple, right?_

Imagine another scenario in which your team manager informed you that there is a need to consume a zip code API to automatically fill in the user's address in the HTML form.

To solve the following problem follow the example below:


```js

class AddressBuilder {

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

    addCEP(cep) {
        this.address.cep = cep;
    }

    addState(state) {
        this.address.state = state;
    }

    addCity(city) {
        this.address.city = city;
    }

    addStreet(street) {
        this.address.street = street;
    }

    getAddress() {
        return this.address;
    }
}

class CepFetcher {
    static url = 'https://brasilapi.com.br/api/cep/v1'
    constructor(builder) {
        this.builder = builder;
    }

    async fetchData(cep) {
        const { cep, state, city, street } = await fetch(`${url}/${this.cep}`).then(response => response.json())
        const data = { cep, state,  city, street };

        this.builder.addCEP(data.cep);
        this.builder.addState(data.state);
        this.builder.addCity(data.city);
        this.builder.addStreet(data.street);
    }
}

const builder = new AddressBuilder();
const fetcher = new CepFetcher(builder);
fetcher.fetchData('01001000');
const address = builder.getAddress();
console.log(address);

```

The _AddressBuilder_ class is responsible for building the address object. It has an empty constructor method that creates an empty address object. It also has methods for adding zip, state, city, and street to the data structure, and a _getAddress()_ method that returns the complete address object.

The _CepFetcher_ class is used to get address information from a ZIP Code API using the URL of the API. It has a builder method that takes an instance of _AddressBuilder_ and a _fetchData()_ method that uses the provided zip code to get the data from the API using fetch() . It then de-structures the API response to extract the zip, state, city, and street data. This data is then passed to the corresponding methods of the _AddressBuilder_ class to add it to the data structure. Finally, the _fetchData_ method returns the complete address object when calling the _getAddress()_ method.

There are some common situations where the Builder pattern is useful, which are:

- When you need to build objects with many optional attributes or variables, the _Builder_ pattern can help you keep the code clear and simple, allowing you to build objects step by step.
- When you need to build complex objects that require multiple steps or specific construction rules, the _Builder_ pattern allows you to encapsulate this logic and easily reuse it.
- When you need to build objects that represent hierarchical data structures, the _Builder_ pattern can help you organize building objects into logical steps.
- When you need to build objects that can be dynamically modified, the _Builder_ pattern allows you to easily add or remove elements from an object.
- When you need to create objects that consume data from an api, the pattern builder can help organize and keep the object construction logic consistent with the data returned by the api.


**Conclusion**

The _Builder_ pattern allows you to keep your code clean and simple, especially when working with complex objects with many optional attributes or variables.

_Builder_ can be useful for many situations, some of them include:


- When you need to build complex objects that require multiple steps or specific construction rules, the Builder pattern lets you encapsulate that logic and easily reuse it.
- When you need to build objects that can be dynamically modified, the Builder pattern allows you to easily add or remove elements from an object.
- When you need to create objects that consume data from an API, the Builder pattern can help you organize and keep object construction logic consistent with the data returned by the API.
- When you need to build objects from different types of data sources (files, api, database) and need to keep the construction logic consistent, pattern builder can be a great choice.


Hope this helps, until next time.