Menu
Coddy logo textTech

Padrão Builder

Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 67 de 87.

O Builder Pattern (Padrão Builder) é um padrão de projeto criacional que resolve um problema comum: construir objetos complexos com muitos parâmetros opcionais. Em vez de criar múltiplos construtores ou passar null para parâmetros não utilizados, o Builder permite que você construa objetos passo a passo.

Considere a criação de um objeto User com campos obrigatórios (name, email) e opcionais (age, phone, address). Sem um Builder, você precisaria de construtores telescópicos ou de um construtor confuso com muitos parâmetros. O padrão Builder oferece uma abordagem mais limpa:

public class User {
    private final String name;    // obrigatório
    private final String email;   // obrigatório
    private final int age;        // opcional
    private final String phone;   // opcional
    
    private User(UserBuilder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.age = builder.age;
        this.phone = builder.phone;
    }
    
    public static class UserBuilder {
        private final String name;
        private final String email;
        private int age;
        private String phone;
        
        public UserBuilder(String name, String email) {
            this.name = name;
            this.email = email;
        }
        
        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }
        
        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }
        
        public User build() {
            return new User(this);
        }
    }
}

Os métodos do Builder retornam this, permitindo o encadeamento de métodos—uma maneira fluida e legível de construir objetos:

User user = new User.UserBuilder("Alice", "alice@email.com")
    .age(25)
    .phone("555-1234")
    .build();

Observe como o construtor User é privado—objetos só podem ser criados através do Builder. Este padrão se destaca quando os objetos possuem muitos campos opcionais, tornando seu código mais legível e menos propenso a erros do que longas listas de parâmetros.

challenge icon

Desafio

Fácil

Vamos construir um sistema de pedidos de pizza usando o Builder Pattern! Em vez de lidar com um construtor que recebe dezenas de parâmetros para todas as coberturas e opções possíveis, você criará um builder fluente que torna a personalização da pizza limpa e legível.

Você organizará seu código em dois arquivos:

  • Pizza.java: Crie uma classe Pizza que use o Builder Pattern para construção. Sua pizza deve ter os seguintes campos:

    size (String) - obrigatório, representa o tamanho da pizza

    cheese (boolean) - opcional, o padrão é false

    pepperoni (boolean) - opcional, o padrão é false

    mushrooms (boolean) - opcional, o padrão é false

    O construtor de Pizza deve ser privado e aceitar apenas um PizzaBuilder como seu parâmetro, copiando todos os valores do builder para os campos da pizza.

    Inclua um método getDescription() que retorne uma string neste formato: [size] Pizza with: [toppings] onde toppings é uma lista separada por vírgulas das coberturas que são true (Cheese, Pepperoni, Mushrooms). Se nenhuma cobertura for selecionada, a parte das coberturas deve apenas dizer no toppings.

    Crie uma classe interna estática PizzaBuilder com:

    • Um construtor que recebe o parâmetro obrigatório size
    • Métodos cheese(), pepperoni() e mushrooms() que cada um define seu respectivo booleano como true e retorna this para encadeamento
    • Um método build() que retorna uma nova Pizza
  • Main.java: Demonstre seu pizza builder em ação! Você receberá quatro entradas: o tamanho da pizza (String) e três valores yes/no (Strings) indicando se deve adicionar queijo, pepperoni e cogumelos, respectivamente.

    Crie um PizzaBuilder com o tamanho fornecido. Então, com base em cada entrada yes/no, encadeie os métodos de cobertura apropriados. Se a entrada for "yes", chame esse método de cobertura; se for "no", pule-o. Finalmente, chame build() para criar sua pizza.

    Imprima o resultado da chamada de getDescription() em sua pizza finalizada.

Você receberá quatro entradas em ordem: size (String), add cheese (String: "yes" or "no"), add pepperoni (String: "yes" or "no"), add mushrooms (String: "yes" or "no").

Por exemplo, com as entradas Large, yes, no, yes, sua saída seria: Large Pizza with: Cheese, Mushrooms

Observe como o Builder Pattern permite construir pizzas com qualquer combinação de coberturas sem a necessidade de construtores separados para cada possibilidade!

Folha de consulta

O Builder Pattern (Padrão de Projeto Construtor) é um padrão de projeto criacional para construir objetos complexos com muitos parâmetros opcionais. Ele evita construtores telescópicos e longas listas de parâmetros ao construir objetos passo a passo.

Estrutura

O padrão consiste em:

  • Uma classe com um construtor privado que aceita apenas um builder
  • Uma classe Builder interna estática que constrói o objeto
  • Métodos Builder que retornam this para encadeamento de métodos
  • Um método build() que cria o objeto final

Exemplo de Implementação

public class User {
    private final String name;    // obrigatório
    private final String email;   // obrigatório
    private final int age;        // opcional
    private final String phone;   // opcional
    
    private User(UserBuilder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.age = builder.age;
        this.phone = builder.phone;
    }
    
    public static class UserBuilder {
        private final String name;
        private final String email;
        private int age;
        private String phone;
        
        public UserBuilder(String name, String email) {
            this.name = name;
            this.email = email;
        }
        
        public UserBuilder age(int age) {
            this.age = age;
            return this;
        }
        
        public UserBuilder phone(String phone) {
            this.phone = phone;
            return this;
        }
        
        public User build() {
            return new User(this);
        }
    }
}

Uso com Encadeamento de Métodos

User user = new User.UserBuilder("Alice", "alice@email.com")
    .age(25)
    .phone("555-1234")
    .build();

O padrão Builder é ideal quando os objetos possuem muitos campos opcionais, proporcionando um código legível e de fácil manutenção em comparação com construtores com inúmeros parâmetros.

Experimente você mesmo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Ler entradas
        String size = scanner.nextLine();
        String addCheese = scanner.nextLine();
        String addPepperoni = scanner.nextLine();
        String addMushrooms = scanner.nextLine();
        
        // TODO: Criar um PizzaBuilder com o tamanho fornecido
        // TODO: Encadeie os métodos de cobertura com base nas entradas yes/no
        // TODO: Construa a pizza e imprima sua descrição
        
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos