O padrão Builder foi originalmente descrito por Gamma et al. em seu livro "Design Patterns: Elements of Reusable Object-Oriented Software" (1994). Nele, os autores apresentam o padrão Builder como uma maneira de separar a construção de um objeto complexo de sua representação, de modo que o mesmo processo de construção possa criar diferentes representações.
O padrão Builder é um padrão de criação que se concentra em separar a construção de um objeto complexo de sua representação, de modo que o mesmo processo de construção possa criar diferentes representações. Ele permite que você construa objetos passo a passo, adicionando diferentes partes ou características a eles ao longo do tempo.
Em geral, o Builder é usado quando se quer criar objetos complexos que possuem muitas partes ou configurações diferentes e que são construídos através de vários passos. O Builder fornece uma interface para especificar esses passos e adicionar as partes ou características apropriadas ao objeto.
Existem duas principais partes envolvidas no padrão Builder, que são:
- O Builder: que é uma interface para especificar os passos para criar o objeto complexo. Ele define os métodos para adicionar as diferentes partes ou características do objeto.
- O Director: que é o objeto que controla o processo de construção usando o Builder especificado. Ele pode criar vários tipos de objetos diferentes usando a mesma sequência de passos, mas com diferentes partes ou características.
Há várias vantagens em usar o padrão Builder em seu código, que são:
- Encapsulamento: o padrão Builder permite que você esconda a lógica de construção de um objeto complexo dentro do Builder e do Director, em vez de expô-lo diretamente ao cliente. Isso torna o código mais fácil de entender e manter.
- Flexibilidade: o padrão Builder permite que você crie diferentes representações de um objeto complexo usando a mesma sequência de passos. Isso significa que você pode criar novas representações sem afetar o código existente.
- Reutilização: o padrão Builder permite que você reutilize a lógica de construção de um objeto complexo em diferentes contextos. Isso significa que você pode construir objetos semelhantes usando a mesma lógica de construção.
- Clareza: o padrão Builder torna o código mais claro e organizado, pois separa a lógica de construção da lógica do sistema. Isso significa que você pode entender facilmente como um objeto é construído e como ele é usado.
- Simplicidade: O padrão Builder simplifica a construção de objetos complexos, pois fornece uma forma organizada de adicionar diferentes partes ou características a um objeto ao longo do tempo.
- Código limpo: Ao dividir a construção de um objeto complexo em passos, ele pode tornar o código mais limpo e mais fácil de manter, pois cada passo é isolado e mais fácil de entender.
Segue abaixo um simples exemplo de código usando o padrão Builder.
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);
A classe SandwichBuilder é responsável por construir uma instância da classe Sandwich adicionando diferentes partes. Ela tem métodos para adicionar pão, queijo, alface e carne e um método "getSandwich" que retorna o objeto sandwich construído.
A classe Sandwich é uma classe modelo que representa o objeto sandwich. O construtor inicia o objeto com todos os seus atributos como false, e os métodos de adição do sandwichBuilder irão alterar os valores.
A classe SandwichMaker é responsável por usar o objeto SandwichBuilder e fazer o sanduíche, é um objeto que controla o processo de construção usando o Builder especificado. A classe tem método para setar um Builder (sandwichBuilder) e outro método para fazer o sandwich(makeSandwich).
Por fim iniciamos uma nova instância da classe SandwichBuilder chamada sandwichBuilder. Em seguida, criamos uma nova instância da classe SandwichMaker chamada sandwichMaker.
Depois disso, configuramos o sandwichMaker para usar o sandwichBuilder especificado com o método setBuilder(sandwichBuilder). Isso significa que a classe SandwichMaker usará o sandwichBuilder para construir o sandwich.
Finalmente, usamos o método makeSandwich() do sandwichMaker para construir o sandwich e armazenamos o resultado na variável mySandwich. Por fim, usamos o console.log para imprimir o sanduíche construído na tela. O resultado seria um objeto sandwich com todos os seus atributos como true.
Simples, né?
Imagine outro cenário na qual a sua gestora de equipe informou que há uma necessidade de consumo de uma API de cep para preenhcimento automático do endereço do usuário no formulário HTML.
Para resolver a seguinte problemática segue o exemplo abaixo:
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);
A classe AddressBuilder é responsável por construir o objeto endereço. Ele tem um método construtor vazio que cria um objeto endereço vazio. Ele também tem métodos para adicionar CEP, Estado, Cidade e Rua à estrutura de dados e um método getAddress() que retorna o objeto endereço completo.
A classe CepFetcher é usada para obter informações de endereço a partir de uma API de CEP usando a URL da API. Ele tem um método construtor que recebe uma instância de AddressBuilder e um método fetchData() que usa o CEP fornecido para obter os dados da API usando o fetch() . Ele então desestrutura a resposta da API para extrair os dados de CEP, estado, cidade e rua. Esses dados são então passados para os métodos correspondentes da classe AddressBuilder para adicioná-los à estrutura de dados. Por fim, o metodo fetchData retorna o objeto endereço completo ao ser chamado o metodo getAddress().
Existe algumas situações comuns que o padrão Builder é útil, que são:
- Quando você precisa construir objetos com muitos atributos opcionais ou variáveis, o padrão Builder pode ajudá-lo a manter a clareza e a simplicidade do código, permitindo que você construa objetos passo a passo.
- Quando você precisa construir objetos complexos que requerem várias etapas ou regras específicas de construção, o padrão Builder permite que você encapsule essa lógica e a reutilize facilmente.
- Quando você precisa construir objetos que representam estruturas de dados hierárquicas, o padrão Builder pode ajudá-lo a organizar a construção de objetos em etapas lógicas.
- Quando você precisa construir objetos que podem ser modificados dinamicamente, o padrão Builder permite que você adicione ou remova elementos de um objeto facilmente.
- Quando você precisa criar objetos que consomem dados de uma api, o pattern builder pode ajuda a organizar e manter a lógica de construção de objetos consistente com os dados retornados pela api.
Conclusão
O padrão Builder permite manter a clareza e a simplicidade do código, principalmente quando se trabalha com objetos complexos com muitos atributos opcionais ou variáveis.
O Builder pode ser útil para várias situações, algumas delas incluem:
- Quando você precisa construir objetos complexos que requerem várias etapas ou regras específicas de construção, o padrão Builder permite que você encapsule essa lógica e a reutilize facilmente.
- Quando você precisa construir objetos que podem ser modificados dinamicamente, o padrão Builder permite que você adicione ou remova elementos de um objeto facilmente.
- Quando você precisa criar objetos que consomem dados de uma API, o padrão Builder pode ajudá-lo a organizar e manter a lógica de construção de objetos consistente com os dados retornados pela API.
- Quando você precisa construir objetos a partir de diferentes tipos de fontes de dados (arquivos, api, base de dados) e precisa manter a lógica de construção consistente, pattern builder pode ser uma ótima escolha.
Espero ter ajudado, até a próxima.
Top comments (0)