Design Patterns in C++: Complete Guide with Examples

онлайн тренажер по питону
Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction to Design Patterns in C++



Design patterns are time-tested architectural solutions for typical development tasks. In the world of C++, they are especially important as they allow creating flexible, extensible, and maintainable code. In this article, we will cover four fundamental patterns: Singleton, Factory Method, Observer, and Strategy — with complete examples in modern C++ (C++17/20).



Each pattern will be accompanied by a practical example, a class diagram, and explanations of its application. The material is intended for developers already familiar with the basics of C++ and OOP.



1. Creational Pattern Singleton



Singleton guarantees that a class has only one instance and provides a global point of access to it. In C++, the classic implementation uses a static method and a private constructor.



When to apply

  • Managing a database connection
  • Logging system
  • Cache manager
  • Application configuration


Implementation example (thread-safe Singleton)



#include <iostream>#include <mutex>#include <memory>

class Logger {private: static std::unique_ptr<Logger> instance; static std::mutex mtx; Logger() { std::cout << "Logger created" << std::endl; } public: Logger(const Logger&) = delete; Logger& operator=(const Logger&) = delete; static Logger* getInstance() { std::lock_guard<std::mutex> lock(mtx); if (!instance) { instance.reset(new Logger()); } return instance.get(); } void log(const std::string& msg) { std::cout << "[LOG] " << msg << std::endl; }};

std::unique_ptr<Logger> Logger::instance = nullptr;std::mutex Logger::mtx;

int main() { Logger* log1 = Logger::getInstance(); Logger* log2 = Logger::getInstance(); log1->log("Test message"); // log1 and log2 point to the same object std::cout << "log1 == log2: " << (log1 == log2) << std::endl; return 0;}


Modern C++ approach (Meyers' Singleton)



class ConfigManager {public:    static ConfigManager& getInstance() {        static ConfigManager instance;  // thread-safe in C++11+        return instance;    }        void setParam(const std::string& key, const std::string& value) {        params[key] = value;    }        std::string getParam(const std::string& key) {        return params[key];    }    private:    ConfigManager() = default;    std::map<std::string, std::string> params;};


2. Creational Pattern Factory Method



Factory Method defines an interface for creating an object but lets subclasses decide which concrete class to instantiate. This pattern is especially useful when the type of object is not known in advance.



Pattern structure

  • Product — abstract product class
  • ConcreteProduct — concrete product implementation
  • Creator — abstract creator class with a factory method
  • ConcreteCreator — overrides the factory method


Example: notification system



#include <iostream>#include <memory>#include <string>

// Abstract productclass Notification {public: virtual void send(const std::string& message) = 0; virtual ~Notification() = default;};

// Concrete productsclass EmailNotification : public Notification {public: void send(const std::str

Blogs

Book Recommendations