Criação Flexível de Objetos com o Padrão Builder em JavaScript
Você tem uma função que cria objetos de usuário. Ela começa com três parâmetros, depois cresce para cinco, depois sete. Metade deles são opcionais. Quem chama a função precisa lembrar a ordem exata, e uma posição errada produz silenciosamente um objeto quebrado. Este é o problema que o Padrão Builder em JavaScript resolve.
Principais Conclusões
- O Padrão Builder constrói objetos passo a passo usando métodos setter encadeados e uma chamada final
build(), substituindo listas de argumentos posicionais propensas a erros. - Uma API fluente, onde cada setter retorna
this, torna o ponto de chamada autodocumentado e independente de ordem. - Reserve o padrão para objetos com muitos parâmetros opcionais, validação de campos obrigatórios ou regras de validação. Para casos mais simples, use literais de objeto ou funções factory.
- O método
build()é o único lugar para validar campos obrigatórios e retornar um objeto limpo e congelado, separado do próprio builder.
O Que É o Padrão Builder em JavaScript?
O Padrão Builder é um padrão de projeto criacional que constrói objetos passo a passo em vez de tudo de uma vez. Em vez de passar todos os valores em uma única chamada de construtor, você encadeia métodos setter e finaliza a criação com uma etapa build() que valida e retorna o objeto completo.
Não é uma solução universal. Para objetos simples com dois ou três campos bem definidos, um literal de objeto simples ou uma função factory é mais limpo. O Padrão Builder ganha seu espaço quando a criação de objetos envolve:
- Muitos parâmetros opcionais onde a ordem não importa
- Regras de validação que devem ser executadas antes do objeto ser usado
- Campos obrigatórios que precisam ser validados no momento da criação
- Construção em múltiplas etapas onde estados intermediários não devem ser expostos
O Problema: Poluição do Construtor
Considere este padrão comum:
// ❌ Difícil de ler, fácil de confundir a ordem dos argumentos
const request = new ApiRequest('GET', '/users', null, true, 5000, 'json')
Seis argumentos posicionais. Sem rótulos. Sem validação. Se você trocar dois valores, nada te avisa.
Um Exemplo Limpo do Padrão Builder em JavaScript
Aqui está uma implementação baseada em classe usando uma API fluente em JavaScript—onde cada setter retorna this, permitindo o encadeamento de métodos:
class ApiRequestBuilder {
constructor() {
this.method = 'GET' // sensible default
this.url = null
this.body = null
this.timeout = 3000 // default timeout
this.responseType = 'json'
}
setMethod(method) {
this.method = method
return this
}
setUrl(url) {
this.url = url
return this
}
setBody(body) {
this.body = body
return this
}
setTimeout(ms) {
this.timeout = ms
return this
}
build() {
if (!this.url) {
throw new Error('URL is required')
}
// Return a plain, frozen object—not the builder itself
return Object.freeze({
method: this.method,
url: this.url,
body: this.body,
timeout: this.timeout,
responseType: this.responseType,
})
}
}
// Usage
const request = new ApiRequestBuilder()
.setUrl('/api/users')
.setMethod('POST')
.setBody({ name: 'Alice' })
.build()
Cada chamada é autodocumentada. A validação é executada em build() antes do objeto ser usado. Valores padrão são aplicados automaticamente. Note que build() retorna um objeto simples congelado—não o builder—o que mantém o resultado limpo e previne mutação acidental.
Discover how at OpenReplay.com.
Builder vs. Alternativas Mais Simples
| Cenário | Melhor Abordagem |
|---|---|
| 2–3 campos obrigatórios, sem validação | Literal de objeto ou função factory |
| Campos opcionais, sem regras | Parâmetros nomeados via createUser({ name, age }) |
| Campos obrigatórios + validação + padrões | Padrão Builder |
| Construção complexa em múltiplas etapas | Padrão Builder |
Uma função factory com parâmetros nomeados como createRequest({ url, method = 'GET' }) lida com muitos casos de forma limpa. Recorra a um builder quando a lógica de validação ou sequenciamento tornar essa função difícil de entender.
Uma Nota sobre TypeScript
TypeScript pode tornar os builders significativamente mais seguros. Você pode garantir que build() só seja chamável depois que os setters obrigatórios foram chamados, usando tipos condicionais ou uma interface step-builder. Se seu projeto usa TypeScript, vale a pena explorar—mas o padrão JavaScript básico funciona bem sem ele.
Conclusão
Use o Padrão Builder quando a criação de objetos tiver regras que precisam ser validadas, não apenas como uma estratégia padrão de criação de objetos. A API fluente torna o ponto de chamada legível, a etapa build() torna a validação explícita, e valores padrão reduzem ruído. Para tudo mais simples, uma função factory ou literal de objeto simples é a ferramenta certa.
Perguntas Frequentes
Um objeto de opções agrupa parâmetros nomeados, o que resolve o problema de argumentos posicionais. Um builder adiciona uma etapa build onde você pode validar campos obrigatórios, impor restrições e congelar o resultado antes de ser usado. Se você precisa dessas garantias, um builder é a melhor escolha. Se você só precisa de chaves nomeadas com valores padrão, um objeto de opções é mais simples.
Sim, mas tenha cuidado. Depois de chamar build, o builder ainda mantém o estado da configuração anterior. Você deve resetar cada campo ou criar uma nova instância do builder para cada objeto. Criar uma nova instância cada vez é a abordagem mais segura e previsível.
Pode adicionar. Se seu objeto tem apenas alguns campos bem conhecidos e nenhuma regra de validação, um literal de objeto simples ou uma função factory com parâmetros nomeados é mais limpo. O Padrão Builder compensa quando o número de campos opcionais cresce, quando os padrões interagem, ou quando a criação requer restrições validadas.
Object.freeze impede que propriedades de nível superior no objeto retornado sejam alteradas após a criação. Isso mantém o resultado construído previsível e somente leitura, o que é especialmente útil quando o objeto é passado por múltiplas camadas de código. Ele desenha uma fronteira clara entre o tempo de configuração dentro do builder e o tempo de uso fora dele.
Truly understand users experience
See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..