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 tem muitos parâmetros opcionais ou exige uma sequência específica de construção.
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 ao 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 Builder ao construir objetos com muitos componentes opcionais, quando quiser um código de construção legível ou quando o mesmo processo de construção precisar criar diferentes representações.
Desafio
FácilVamos criar um sistema Computer Builder que permita aos usuários configurar PCs personalizados passo a passo. Este é um cenário perfeito para o padrão Builder: os 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 de produto que representa um computador totalmente configurado.Sua classe
Computerdeve armazenar estes componentes como membros privados:cpu(string),ram(string),storage(string),gpu(string) ehasWifi(booleano). InicializehasWificomofalsee as strings como vazias por padrão.Adicione um método público chamado
showSpecs()que exiba a configuração do computador. Para cada componente que tiver sido definido (string não vazia), imprima-o em sua própria linha. A capacidade de wifi só deve ser impressa se estiver habilitada.ComputerBuilder.h: Crie a classe construtora que monta computadores com uma interface fluente.Sua classe
ComputerBuilderdeve ter um membro privadoComputerque ela monta gradualmente. Implemente estes métodos, cada um retornando uma referência à construtora 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(): habilita a capacidade de wifi
Implemente também um método
build()que retorne o objetoComputerconcluído e redefina a construtora para possível reutilização.main.cpp: Reúna tudo para montar um computador personalizado.Leia quatro entradas:
- Modelo da CPU (string)
- Especificação da RAM (string)
- Especificação do armazenamento (string)
- Se deve incluir wifi:
yesouno
Use
ComputerBuilderpara construir um computador com a CPU, a RAM e o armazenamento fornecidos. Se a entrada de wifi foryes, chame tambémaddWifi(). Observe que nenhuma GPU é especificada nesta configuração: a construtora deve lidar normalmente com componentes opcionais.Depois da construção, chame
showSpecs()no computador resultante para exibir sua configuração.
O método showSpecs() deve produzir neste formato (mostrando apenas os componentes que foram definidos):
CPU: [value]
RAM: [value]
Storage: [value]
GPU: [value]
Wifi: EnabledPor 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: EnabledCom as entradas AMD Ryzen 5 5600X, 16GB DDR4, 512GB SSD e no:
CPU: AMD Ryzen 5 5600X
RAM: 16GB DDR4
Storage: 512GB SSDObserve como o padrão Builder torna o processo de construção legível e flexível. Você pode adicionar ou ignorar componentes facilmente, e o encadeamento de métodos cria um código claro e autoexplicativo. A linha da GPU não aparece porque nunca a definimos, demonstrando como as construtoras lidam naturalmente com componentes opcionais.
Experimente você mesmo
#include <iostream>
#include <string>
#include "ComputerBuilder.h"
using namespace std;
int main() {
// Ler entradas
string cpu, ram, storage, wifiChoice;
getline(cin, cpu);
getline(cin, ram);
getline(cin, storage);
getline(cin, wifiChoice);
// TODO: Crie uma instância de ComputerBuilder
// TODO: Use encadeamento de métodos para definir CPU, RAM e storage
// TODO: Se wifiChoice for "yes", também chame addWifi()
// TODO: Chame build() para obter o objeto Computer
// TODO: Chame showSpecs() no computador construído para exibir a configuração
return 0;
}
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
1Fundamentos de POO
Arquivos externosBuild e compilação em C++Arquivos de cabeçalho e arquivos-fonteNamespaces e escopoIntrodução à POO em C++Classes vs. objetosO ponteiro 'this'Métodos (funções membro)Atributos (membros de dados)Noções básicas de construtores e destruidoresRevisão - calculadora simples4Propriedades de Classe
Membros de Instância vs. EstáticosGetters e SettersFunções Membro ConstPalavra-chave MutableMétodos e Variáveis EstáticosFunções e Classes FriendRevisão - Gerenciador de Contas Bancárias7Herança
Herança básicaNíveis de acesso da herançaOrdem de chamada de construtor e destrutorSobrescrita de métodosFunções virtuais e VTableHerança múltiplaHerança virtualRevisão - Hierarquia de funcionários10Visão geral da STL
Visão geral e filosofia da STLContêineres da STLIteradoresAlgoritmos da STLFunctors e expressões lambdaRecapitulação - Frequência de palavras13Padrões de Projeto — Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonFactory e Abstract FactoryPadrão BuilderPadrão ObserverPadrão Strategy2Gerenciamento de Memória
Memória Stack vs. HeapPonteiros e ReferênciasMemória Dinâmica (new/delete)Ponteiros Inteligentes em C++RAII em C++Revisão - Gerenciador de Array Dinâmico5Encapsulamento
Especificadores de acesso em C++Especificadores de acesso em profundidadeOcultação de informaçõesStruct vs ClasseClasses aninhadas e internasRecapitulação - Sistema de registros de alunos8Polimorfismo
Polimorfismo em compilação vs. execuçãoSobrecarga de funçõesFunções virtuais revisadasFunções virtuais purasClasses abstratasDesign de interfaces em C++Conversão dinâmica e RTTIRecapitulação — Calculadora de formas11Conceitos Avançados de OOP
Composição vs. HerançaMixins via CRTPIdioma PimplApagamento de TiposClasses Enum e Tipagem ForteTratamento de Exceções em OOPHierarquias de Exceções Personalizadas14Padrões de Projeto — Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositeRAII como Padrão3Construtores e Destrutores
Construtor PadrãoConstrutor ParametrizadoConstrutor de CópiaConstrutor de MovimentoListas de Inicialização do ConstrutorConstrutores DelegantesAprofundamento em DestrutoresRegra dos Três / Cinco / ZeroRevisão - Classe String6Sobrecarga de Operadores
Introdução à Sobrecarga de OperadoresSobrecarga de Operadores AritméticosSobrecarga de Operadores de ComparaçãoOperadores de FluxoSobrecarga do Operador de AtribuiçãoSobrecarga dos Operadores [] e ()Operadores de Conversão de TipoRecapitulação - Classe Matrix9Templates
Templates de FunçõesTemplates de ClassesEspecialização de TemplatesTemplates VariádicosNoções Básicas de SFINAE e Traits de TiposRecapitulação - Contêiner GenéricoPratique por conta própria: Compilador de C++ online