🖥️
Padrões de Projeto
  • Padrões de Projeto
  • Orientação a Objetos
    • Conceitos básicos de orientação a objetos
      • Objetos e classes
      • Encapsulamento
      • Relacionamentos
      • Herança
      • Realização
      • Polimorfismo
      • Imutabilidade
  • Princípios SOLID
    • Introdução
    • SRP - Princípio de Responsabilidade Única
    • OCP - Princípio de Aberto/Fechado
    • LSP - Princípio de Substituição de Liskov
    • ISP - Princípio de Segregação de Interfaces
    • DIP - Princípio de Inversão de Dependência
  • Padrões de Projetos e catálogos
    • Introdução
  • Padrões Comportamentais
    • Padrão Strategy
    • Padrão State
    • Padrão Observer
    • Padrão Chain of Responsibility
    • Padrão Command
    • Padrão Template Method
    • Padrão Null Object
  • Padrões Criacionais
    • Padrão Singleton
    • Padrão Prototype
    • Padrão Builder
    • Padrões Factory
      • Factory Method
      • Abstract Factory
  • Padrões Estruturais
  • Padrão Adapter
  • Padrão Facade
  • Padrão Decorator
  • Padrão Proxy
  • Padrão Bridge
  • Padrão Composite
Powered by GitBook
On this page
  • Problema
  • Solução
  • Exemplos de Builder na API nativa do Java

Was this helpful?

  1. Padrões Criacionais

Padrão Builder

PreviousPadrão PrototypeNextPadrões Factory

Last updated 4 years ago

Was this helpful?

Antes de começar a entender o padrão Builder, é interessante que veja o assunto de .

O Builder é um padrão de projeto criacional que permite a você construir objetos complexos passo a passo. Ele permite que você produza diferentes tipos e representações de um objeto usando o mesmo código de construção.

Problema

Imagine um objeto complexo que necessite de uma inicialização passo a passo trabalhosa de muitos campos e objetos agrupados. Tal código de inicialização fica geralmente enterrado dentro de um construtor monstruoso com vários parâmetros. Ou pior: espalhado por todo o código cliente.

Considere uma classe Usuário que tenha vários atributos, sendo uns obrigatórios, outros opcionais. Além disso, queremos criar um objeto , ou seja, todos os seus atributos devem ser marcados como final.

public class Usuario {

    private final String nome;
    private final String sobrenome;
    private final Integer idade;
    private final String telefone;
    private final String endereco;

    // Gets e sets
    
}

Uma vez que usamos construtores para criar objetos dessa classe, como poderiamos trazer essa abordagem de atributos obrigatórios e opcionais? Pare e pense por um momento e verá que criar vários construtores provavelmente não vai resolver esse cenário.

Solução

O padrão Builder sugere que você extraia o código de construção do objeto para fora de sua própria classe e mova ele para objetos separados chamados builders. “Builder” significa “construtor”, mas não usaremos essa palavra para evitar confusão com os construtores de classe.

O padrão organiza a construção de objetos em uma série de etapas (comNome, comSobrenome, etc.). Para criar um objeto você executa uma série de etapas em um objeto builder. A parte importante é que você não precisa chamar todas as etapas. Você chama apenas aquelas etapas que são necessárias para a produção de uma configuração específica de um objeto, no nosso caso, os atributos que são obrigatórios. Observe o exemplo abaixo:

public class UsuarioBuilder {

    private String nome;
    private String sobrenome;
    private Integer idade;
    private String telefone;
    private String endereco;

    public UsuarioBuilder() {
    }

    public UsuarioBuilder comNome(String nome) {
        this.nome = nome;
        return this;
    }

    public UsuarioBuilder comSobrenome(String sobrenome) {
        this.sobrenome = sobrenome;
        return this;
    }

    public UsuarioBuilder comIdade(Integer idade) {
        this.idade = idade;
        return this;
    }

    public UsuarioBuilder comTelefone(String telefone) {
        this.telefone = telefone;
        return this;
    }

    public UsuarioBuilder comEndereco(String endereco) {
        this.endereco = endereco;
        return this;
    }

    public Usuario toUsuario() throws UsuarioBuilderException {
        validarUsuario();
        return new Usuario(nome, sobrenome, idade, telefone, endereco);
    }

    private void validarUsuario() throws UsuarioBuilderException {

        if(nome == null || nome.isEmpty()) {
            throw new UsuarioBuilderException();
        }
        if(sobrenome == null || sobrenome.isEmpty()) {
            throw new UsuarioBuilderException();
        }
        if(idade < 18)
            throw new UsuarioBuilderException();
    }
}

Ao finalizar o processo de construção, o método toUsuario() é chamado. Aqui, ainda acrescentamos uma validação para saber se o processo de construção foi bem executado, mas o mesmo poderia ter sido distribuido a medida que os métodos das etapas fossem chamados.

Assim, nosso processo de construção será semelhante ao exemplo abaixo.

UsuarioBuilder builder = new UsuarioBuilder();
builder.comNome("Diogo").comSobrenome("Moreira");
Usuario novoUsuario = builder.toUsuario();

Exemplos de Builder na API nativa do Java

A classe StringBuilder é um exemplo claro do padrão Builder sendo usado para construir objetos imutáveis, nesse caso String.

O padrão Builder permite que você construa objetos passo a passo, usando apenas aquelas etapas que você realmente precisa. Após implementar o padrão, você não vai mais precisar amontoar dúzias de parâmetros em seus construtores. O exemplo completo está .

No exemplo acima, utilizamos uma "técnica" para construir os métodos chamada de Fluent Interface. Veja uma explicação .

Imutabilidade
imutável
nesse repositório
aqui