Menu
Coddy logo textTech

Padrão Builder

Parte da seção Programação Orientada a Objetos do Journey de C++ da Coddy — lição 93 de 104.

O padrão Builder separa a construção de um objeto complexo de sua representação, permitindo que você crie diferentes configurações passo a passo. Isso é especialmente útil quando um objeto possui muitos parâmetros opcionais ou requer uma sequência de construção específica.

Em vez de um construtor com muitos parâmetros (o que se torna confuso), o Builder fornece métodos claros e nomeados para cada opção de configuração:

#include <iostream>
#include <string>

class Pizza {
public:
    std::string dough;
    std::string sauce;
    std::string topping;
    bool cheese;
    
    void describe() const {
        std::cout << dough << " dough, " << sauce << " sauce, "
                  << topping << (cheese ? ", with cheese" : "") << "\n";
    }
};

class PizzaBuilder {
private:
    Pizza pizza;
    
public:
    PizzaBuilder& setDough(const std::string& d) {
        pizza.dough = d;
        return *this;
    }
    
    PizzaBuilder& setSauce(const std::string& s) {
        pizza.sauce = s;
        return *this;
    }
    
    PizzaBuilder& setTopping(const std::string& t) {
        pizza.topping = t;
        return *this;
    }
    
    PizzaBuilder& addCheese() {
        pizza.cheese = true;
        return *this;
    }
    
    Pizza build() { return pizza; }
};

int main() {
    Pizza margherita = PizzaBuilder()
        .setDough("thin")
        .setSauce("tomato")
        .setTopping("basil")
        .addCheese()
        .build();
    
    margherita.describe();
}

Cada método setter retorna uma referência para o builder (return *this), permitindo o encadeamento de métodos para uma interface fluente. O método build() finaliza e retorna o objeto construído.

Use o Builder ao construir objetos com muitos componentes opcionais, quando você deseja um código de construção legível ou quando o mesmo processo de construção deve criar representações diferentes.

challenge icon

Desafio

Fácil

Vamos construir um sistema Computer Builder que permite aos usuários configurar PCs personalizados passo a passo. Este é um cenário perfeito para o padrão Builder — computadores têm muitos componentes opcionais e queremos uma maneira limpa e legível de montar diferentes configurações.

Você organizará seu código em três arquivos:

  • Computer.h: Defina a classe do produto que representa um computador totalmente configurado.

    Sua classe Computer deve armazenar estes componentes como membros privados: cpu (string), ram (string), storage (string), gpu (string) e hasWifi (boolean). Inicialize hasWifi como false e as strings como vazias por padrão.

    Adicione um método público chamado showSpecs() que exibe a configuração do computador. Para cada componente que foi definido (string não vazia), imprima-o em sua própria linha. A capacidade wifi só deve ser impressa se estiver ativada.

  • ComputerBuilder.h: Crie a classe builder que constrói computadores com uma interface fluente.

    Sua classe ComputerBuilder deve ter um membro privado Computer que ela constrói. Implemente estes métodos, cada um retornando uma referência para o builder para permitir o encadeamento de métodos:

    • setCPU(const std::string& cpu)
    • setRAM(const std::string& ram)
    • setStorage(const std::string& storage)
    • setGPU(const std::string& gpu)
    • addWifi() — ativa a capacidade wifi

    Também implemente um método build() que retorna o objeto Computer concluído e redefine o builder para uma possível reutilização.

  • main.cpp: Reúna tudo para construir um computador personalizado.

    Leia quatro entradas:

    1. Modelo da CPU (string)
    2. Especificação da RAM (string)
    3. Especificação do armazenamento (string)
    4. Se deve incluir wifi: yes ou no

    Use o ComputerBuilder para construir um computador com a CPU, RAM e armazenamento fornecidos. Se a entrada de wifi for yes, chame também addWifi(). Observe que nenhuma GPU é especificada nesta configuração — o builder deve lidar com componentes opcionais de forma graciosa.

    Após a construção, chame showSpecs() no computador resultante para exibir sua configuração.

O método showSpecs() deve produzir a saída neste formato (mostrando apenas os componentes que foram definidos):

CPU: [value]
RAM: [value]
Storage: [value]
GPU: [value]
Wifi: Enabled

Por exemplo, com as entradas Intel i7-12700K, 32GB DDR5, 1TB NVMe SSD e yes:

CPU: Intel i7-12700K
RAM: 32GB DDR5
Storage: 1TB NVMe SSD
Wifi: Enabled

Com as entradas AMD Ryzen 5 5600X, 16GB DDR4, 512GB SSD e no:

CPU: AMD Ryzen 5 5600X
RAM: 16GB DDR4
Storage: 512GB SSD

Observe como o padrão Builder torna o processo de construção legível e flexível — você pode facilmente adicionar ou pular componentes, e o encadeamento de métodos cria um código claro e autodocumentado. A linha da GPU não aparece porque nunca a definimos, demonstrando como os builders lidam com componentes opcionais naturalmente.

Folha de consulta

O padrão Builder separa a construção de um objeto complexo de sua representação, permitindo uma configuração passo a passo. É útil quando um objeto possui muitos parâmetros opcionais ou requer uma sequência de construção específica.

Em vez de construtores com muitos parâmetros, o Builder fornece métodos claros e nomeados para cada opção de configuração:

class Pizza {
public:
    std::string dough;
    std::string sauce;
    std::string topping;
    bool cheese;
};

class PizzaBuilder {
private:
    Pizza pizza;
    
public:
    PizzaBuilder& setDough(const std::string& d) {
        pizza.dough = d;
        return *this;  // Enable method chaining
    }
    
    PizzaBuilder& setSauce(const std::string& s) {
        pizza.sauce = s;
        return *this;
    }
    
    PizzaBuilder& setTopping(const std::string& t) {
        pizza.topping = t;
        return *this;
    }
    
    PizzaBuilder& addCheese() {
        pizza.cheese = true;
        return *this;
    }
    
    Pizza build() { return pizza; }
};

// Usage with method chaining
Pizza margherita = PizzaBuilder()
    .setDough("thin")
    .setSauce("tomato")
    .setTopping("basil")
    .addCheese()
    .build();

Cada método setter retorna return *this para permitir o encadeamento de métodos (method chaining) para uma interface fluente. O método build() finaliza e retorna o objeto construído.

Use o Builder ao construir objetos com muitos componentes opcionais, quando desejar um código de construção legível ou quando o mesmo processo de construção deva criar representações diferentes.

Experimente você mesmo

#include <iostream>
#include <string>
#include "ComputerBuilder.h"

using namespace std;

int main() {
    // Ler as entradas
    string cpu, ram, storage, wifiChoice;
    getline(cin, cpu);
    getline(cin, ram);
    getline(cin, storage);
    getline(cin, wifiChoice);

    // TODO: Criar uma instância de ComputerBuilder
    
    // TODO: Usar encadeamento de métodos para definir CPU, RAM e storage
    
    // TODO: Se wifiChoice for "yes", também chame addWifi()
    
    // TODO: Chamar build() para obter o objeto Computer
    
    // TODO: Chamar showSpecs() no computador construído para exibir a configuração

    return 0;
}
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