Patrón Builder
Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 93 de 104.
El patrón Builder separa la construcción de un objeto complejo de su representación, lo que te permite crear distintas configuraciones paso a paso. Esto resulta especialmente útil cuando un objeto tiene muchos parámetros opcionales o requiere una secuencia de construcción específica.
En lugar de un constructor con muchos parámetros (que se vuelve confuso), Builder proporciona métodos claros y con nombres para cada opción de configuración:
#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 devuelve una referencia al builder (return *this), lo que permite encadenar métodos para crear una interfaz fluida. El método build() finaliza y devuelve el objeto construido.
Usa Builder cuando construyas objetos con muchos componentes opcionales, cuando quieras un código de construcción legible o cuando el mismo proceso de construcción deba crear diferentes representaciones.
Desafío
FácilConstruyamos un sistema de Computer Builder que permita a los usuarios configurar PCs personalizados paso a paso. Este es un escenario perfecto para el patrón Builder: los ordenadores tienen muchos componentes opcionales y queremos una forma limpia y legible de ensamblar distintas configuraciones.
Organizarás tu código en tres archivos:
Computer.h: Define la clase de producto que representa un ordenador completamente configurado.Tu clase
Computerdebe almacenar estos componentes como miembros privados:cpu(cadena),ram(cadena),storage(cadena),gpu(cadena) yhasWifi(booleano). InicializahasWificonfalsey las cadenas vacías de forma predeterminada.Añade un método público llamado
showSpecs()que muestre la configuración del ordenador. Para cada componente que se haya establecido (cadena no vacía), imprímelo en su propia línea. La capacidad wifi solo debe imprimirse si está habilitada.ComputerBuilder.h: Crea la clase constructora que construye ordenadores mediante una interfaz fluida.Tu clase
ComputerBuilderdebe tener un miembro privadoComputerque irá construyendo. Implementa estos métodos, cada uno devolviendo una referencia al constructor para permitir el encadenamiento 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 la capacidad wifi
Implementa también un método
build()que devuelva el objetoComputercompletado y restablezca el constructor para poder reutilizarlo.main.cpp: Une todos los elementos para construir un ordenador personalizado.Lee cuatro entradas:
- Modelo de CPU (cadena)
- Especificación de la RAM (cadena)
- Especificación del almacenamiento (cadena)
- Si se debe incluir wifi:
yesono
Usa
ComputerBuilderpara construir un ordenador con la CPU, la RAM y el almacenamiento proporcionados. Si la entrada de wifi esyes, llama también aaddWifi(). Ten en cuenta que no se especifica ninguna GPU en esta configuración: el constructor debe gestionar los componentes opcionales correctamente.Después de construirlo, llama a
showSpecs()en el ordenador resultante para mostrar su configuración.
El método showSpecs() debe mostrar el siguiente formato (mostrando únicamente los componentes que se hayan establecido):
CPU: [value]
RAM: [value]
Storage: [value]
GPU: [value]
Wifi: EnabledPor ejemplo, con las entradas Intel i7-12700K, 32GB DDR5, 1TB NVMe SSD y yes:
CPU: Intel i7-12700K
RAM: 32GB DDR5
Storage: 1TB NVMe SSD
Wifi: EnabledCon las entradas AMD Ryzen 5 5600X, 16GB DDR4, 512GB SSD y no:
CPU: AMD Ryzen 5 5600X
RAM: 16GB DDR4
Storage: 512GB SSDObserva cómo el patrón Builder hace que el proceso de construcción sea legible y flexible. Puedes añadir u omitir componentes fácilmente, y el encadenamiento de métodos crea un código claro y autodocumentado. La línea de la GPU no aparece porque nunca la establecimos, lo que demuestra cómo los constructores gestionan los componentes opcionales de forma natural.
Pruébalo tú mismo
#include <iostream>
#include <string>
#include "ComputerBuilder.h"
using namespace std;
int main() {
// Leer entradas
string cpu, ram, storage, wifiChoice;
getline(cin, cpu);
getline(cin, ram);
getline(cin, storage);
getline(cin, wifiChoice);
// TODO: Crea una instancia de ComputerBuilder
// TODO: Usa el encadenamiento de métodos para establecer CPU, RAM y storage
// TODO: Si wifiChoice es "yes", también llama a addWifi()
// TODO: Llama a build() para obtener el objeto Computer
// TODO: Llama a showSpecs() en la computadora construida para mostrar la configuración
return 0;
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosConstrucción y compilación en C++Archivos de cabecera y archivos fuenteNamespaces y alcanceIntroducción a OOP en C++Clases vs ObjetosEl puntero 'this'Métodos (Funciones miembro)Atributos (Miembros de datos)Conceptos básicos de Ctors y DtorsResumen - Calculadora simple4Propiedades de clase
Miembros de instancia vs. estáticosGetters y SettersFunciones miembro constPalabra clave mutableMétodos y variables estáticosFunciones y clases amigasResumen - Gestor de cuentas bancarias7Herencia
Herencia básicaNiveles de acceso en la herenciaOrden de llamada de Ctor y DtorSobrescritura de métodosFunciones virtuales y VTableHerencia múltipleHerencia virtualResumen - Jerarquía de empleados10Visión general de la STL
Visión general y filosofía de la STLContenedores de la STLIteradoresAlgoritmos de la STLFuntores y expresiones lambdaResumen - Frecuencia de palabras13Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonFactory y Abstract FactoryPatrón BuilderPatrón ObserverPatrón Strategy2Gestión de memoria
Memoria Stack vs HeapPunteros y referenciasMemoria dinámica (new/delete)Punteros inteligentes en C++RAII en C++Resumen - Gestor de arrays dinámicos5Encapsulamiento
Especificadores de acceso en C++Especificadores de acceso en profundidadOcultamiento de informaciónStruct vs ClassClases anidadas e internasResumen - Sistema de registros de estudiantes8Polimorfismo
Polimorfismo: Compilación vs. Tiempo de ejecuciónSobrecarga de funcionesFunciones virtuales revisadasFunciones virtuales purasClases abstractasDiseño de interfaces en C++Dynamic Casting y RTTIResumen: Calculadora de figuras11Conceptos avanzados de POO
Composición vs. HerenciaMixins mediante CRTPIdioma PimplBorrado de tiposEnum Classes y tipado fuerteManejo de excepciones en POOJerarquías de excepciones personalizadas14Patrones de diseño - Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositeRAII como patrón3Constructores y Destructores
Constructor por defectoConstructor parametrizadoConstructor de copiaConstructor de movimientoListas de inicialización del constructorConstructores delegadosAnálisis profundo del destructorRegla de tres / cinco / ceroResumen - Clase String6Sobrecarga de operadores
Introducción a la sobrecarga de operadoresSobrecarga de operadores aritméticosSobrecarga de operadores de comparaciónOperadores de flujo (Stream)Sobrecarga del operador de asignaciónSobrecarga de los operadores [] y ()Operadores de conversión de tiposResumen - Clase Matrix9Plantillas
Plantillas de funcionesPlantillas de clasesEspecialización de plantillasPlantillas variádicasConceptos básicos de SFINAE y Type TraitsResumen - Contenedor genéricoPractica por tu cuenta: Compilador de C++ online