Patrones de diseño en C++ con ejemplos: análisis completo

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿por qué se necesitan los patrones de diseño en C++?



Los patrones de diseño (design patterns) son soluciones probadas para problemas típicos que surgen durante el desarrollo de software. En C++, con su potente sistema de tipos, RAII y herencia múltiple, los patrones adquieren una flexibilidad especial. Ayudan a que el código sea más legible, mantenible y escalable.



En este artículo, veremos 4 patrones clave del catálogo GoF (Gang of Four): Singleton, Factory Method, Observer y Strategy. Cada patrón se ilustrará con un ejemplo de código real en C++17/20.



Patrones creacionales: Singleton (Instancia única)



Singleton garantiza que una clase tenga una única instancia y proporciona un punto de acceso global a ella. En C++, el enfoque moderno utiliza una variable estática local (thread-safe desde C++11).



Ejemplo: Logger de aplicación



class Logger {public:    // Eliminamos copia y asignación    Logger(const Logger&) = delete;    Logger& operator=(const Logger&) = delete;

static Logger& getInstance() { static Logger instance; // thread-safe desde C++11 return instance; }

void log(const std::string& message) { std::lock_guard<std::mutex> lock(m_mutex); std::cout << "[LOG] " << message << std::endl; }

private: Logger() = default; // constructor privado ~Logger() = default; std::mutex m_mutex;};

// Usoint main() { Logger::getInstance().log("Aplicación iniciada"); Logger::getInstance().log("Error: archivo no encontrado"); return 0;}


Ventajas: garantía de unicidad, inicialización perezosa, seguridad en hilos.
Desventajas: dificulta las pruebas (estado global), viola el principio de responsabilidad única.



Patrones creacionales: Factory Method (Método de fábrica)



Factory Method define una interfaz para crear un objeto, pero permite que las subclases decidan qué clase instanciar. En C++ a menudo se implementa mediante funciones virtuales y punteros inteligentes.



Ejemplo: Generación de diferentes tipos de documentos



// Producto abstractoclass Document {public:    virtual void open() = 0;    virtual void save() = 0;    virtual ~Document() = default;};

// Productos concretosclass PDFDocument : public Document {public: void open() override { std::cout << "PDF abierto"; } void save() override { std::cout << "PDF guardado"; }};

class WordDocument : public Document {public: void open() override { std::cout << "Word abierto"; } void save() override { std::cout << "Word guardado"; }};

// Creador (Creator)class Application {public: virtual std::unique_ptr<Document> createDocument() = 0; virtual ~Application() = default;

void newDocument() { auto doc = createDocument(); doc->open(); // trabajo con el documento }};

// Creadores concretosclass PDFApplication : public Application {public: std::unique_ptr<Document> createDocument() override { return std::make_unique<PDFDocument>(); }};

class WordApplication : public Application {public: std::unique_ptr<Document> createDocument() override { return std::make_unique<WordDocument>(); }};

// Usoint main() { std::unique_ptr<Application> app = std::make_unique<PDFApplication>(); app->newDocument(); // Salida: "PDF abierto" return 0;}


Este patrón es ideal cuando no se conocen de antemano los tipos exactos de los objetos a crear.



Patrones de comportamiento: Observer (Observador)



Blogs

Book Recommendations