Introducción a los patrones de diseño
Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy — lección 90 de 104.
Los patrones de diseño son soluciones probadas y reutilizables para problemas comunes que surgen en el diseño de software. No son código que se copia directamente: son plantillas o planos que describen cómo estructurar clases y objetos para resolver desafíos específicos de manera elegante.
El concepto fue popularizado por el "Gang of Four" (GoF) en su libro de 1994, el cual catalogó 23 patrones fundamentales. Estos patrones se agrupan típicamente en tres categorías:
| Categoría | Propósito | Ejemplos |
|---|---|---|
| Creacionales | Mecanismos de creación de objetos | Singleton, Factory, Builder |
| Estructurales | Composición de clases y objetos | Adapter, Decorator, Composite |
| De comportamiento | Interacción y responsabilidad de los objetos | Observer, Strategy, Command |
¿Por qué aprender patrones de diseño? Proporcionan un vocabulario compartido entre los desarrolladores: decir "usa un Factory aquí" comunica instantáneamente una idea compleja. También te ayudan a evitar reinventar soluciones y hacen que tu código sea más flexible y fácil de mantener.
En C++, los patrones de diseño aprovechan las características de la POO que ya has aprendido: herencia, polimorfismo, clases abstractas y plantillas. A lo largo de las próximas lecciones, implementarás varios patrones esenciales y comprenderás cuándo cada uno es la herramienta adecuada para el trabajo.
Desafío
FácilVamos a construir un clasificador de patrones sencillo que demuestre tu comprensión de las tres categorías de patrones de diseño. Crearás un sistema que tome el nombre de un patrón e identifique a qué categoría pertenece (Creational, Structural o Behavioral), junto con una breve descripción del propósito de esa categoría.
Organizarás tu código en tres archivos:
PatternCategory.h: Define una clase base abstracta llamadaPatternCategoryque represente una categoría de patrón de diseño. Debe tener:- Un método virtual puro
getName()que devuelva el nombre de la categoría como un string. - Un método virtual puro
getPurpose()que devuelva una descripción de lo que hacen los patrones en esta categoría. - Un destructor virtual.
Luego, crea tres clases derivadas que hereden de
PatternCategory:CreationalCategory— devuelve el nombre"Creational"y el propósito"Object creation mechanisms"StructuralCategory— devuelve el nombre"Structural"y el propósito"Class and object composition"BehavioralCategory— devuelve el nombre"Behavioral"y el propósito"Object interaction and responsibility"
- Un método virtual puro
PatternClassifier.h: Crea una clasePatternClassifierque pueda identificar a qué categoría pertenece un patrón dado.Tu clasificador debe tener un método
classifyque reciba el nombre de un patrón (string) y devuelva un puntero a laPatternCategoryapropiada. Utiliza punteros inteligentes (std::unique_ptr) para la gestión de memoria.El clasificador debe reconocer estos patrones:
- Creational:
Singleton,Factory,Builder - Structural:
Adapter,Decorator,Composite - Behavioral:
Observer,Strategy,Command
Si el nombre del patrón no es reconocido, devuelve
nullptr.- Creational:
main.cpp: Lee una única entrada: el nombre de un patrón de diseño.Crea un
PatternClassifiery úsalo para clasificar el patrón de entrada. Si el patrón es reconocido, imprime:[PatternName] is a [CategoryName] pattern Purpose: [CategoryPurpose]Si el patrón no es reconocido, imprime:
Unknown pattern: [PatternName]
Por ejemplo, con la entrada Singleton:
Singleton is a Creational pattern
Purpose: Object creation mechanismsCon la entrada Observer:
Observer is a Behavioral pattern
Purpose: Object interaction and responsibilityCon la entrada Proxy:
Unknown pattern: ProxyEste desafío refuerza las tres categorías de patrones de diseño mientras practicas la herencia, el polimorfismo y los punteros inteligentes, conceptos que ya dominas. La estructura de múltiples archivos refleja cómo los proyectos reales organizan las clases relacionadas.
Hoja de referencia
Los patrones de diseño son soluciones reutilizables a problemas comunes de diseño de software. Sirven como plantillas para estructurar clases y objetos, no como código directo para copiar.
Los patrones de diseño se agrupan en tres categorías principales:
| Categoría | Propósito | Ejemplos |
|---|---|---|
| Creacionales | Mecanismos de creación de objetos | Singleton, Factory, Builder |
| Estructurales | Composición de clases y objetos | Adapter, Decorator, Composite |
| De comportamiento | Interacción y responsabilidad de los objetos | Observer, Strategy, Command |
Beneficios de los patrones de diseño:
- Proporcionan un vocabulario compartido entre los desarrolladores
- Evitan reinventar soluciones a problemas comunes
- Hacen que el código sea más flexible y fácil de mantener
En C++, los patrones de diseño aprovechan las características de la POO, incluyendo la herencia, el polimorfismo, las clases abstractas y las plantillas (templates).
Pruébalo tú mismo
#include <iostream>
#include <string>
#include "PatternClassifier.h"
int main() {
// Lee el nombre del patrón
std::string patternName;
std::cin >> patternName;
// TODO: Crea una instancia de PatternClassifier
// TODO: Usa el clasificador para clasificar el patrón de entrada
// TODO: Si se reconoce el patrón, imprime:
// "[PatternName] is a [CategoryName] pattern"
// "Purpose: [CategoryPurpose]"
// TODO: Si no se reconoce el patrón (nullptr), imprime:
// "Unknown pattern: [PatternName]"
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érico