Какие паттерны проектирования знаешь и когда их применяешь в C++?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерны проектирования в C++
Паттерны проектирования — это проверенные решения типичных задач разработки. В C++ их применение требует особой аккуратности из-за низкоуровневой природы языка.
Структурные паттерны
Singleton — гарантирует единственный экземпляр класса. Используется для глобальных конфигураций, логгеров, пулов соединений:
class Logger {
public:
static Logger& getInstance() {
static Logger instance;
return instance;
}
private:
Logger() = default;
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
};
Factory — создаёт объекты без указания конкретных классов. Полезен при работе с полиморфными типами:
class Connection {
public:
virtual ~Connection() = default;
virtual void connect() = 0;
};
class PostgreSQL : public Connection {
public:
void connect() override { /* ... */ }
};
class ConnectionFactory {
public:
static std::unique_ptr<Connection> create(const std::string& type) {
if (type == "postgres") return std::make_unique<PostgreSQL>();
throw std::invalid_argument("Unknown connection type");
}
};
Adapter — преобразует интерфейс одного класса к другому. Часто используется при интеграции с legacy-кодом или внешними библиотеками.
Поведенческие паттерны
Observer — уведомляет несколько объектов об изменении состояния. Критичен для event-driven архитектур:
class EventBus {
std::map<std::string, std::vector<std::function<void()>>> listeners;
public:
void subscribe(const std::string& event, std::function<void()> handler) {
listeners[event].push_back(handler);
}
void emit(const std::string& event) {
for (auto& handler : listeners[event]) {
handler();
}
}
};
Strategy — инкапсулирует алгоритмы в отдельные классы. Применяется для выбора алгоритма сортировки, сжатия, сериализации в runtime.
Command — инкапсулирует запрос как объект. Используется в системах с отложенным выполнением, undo/redo, планировщиках задач:
class Command {
public:
virtual ~Command() = default;
virtual void execute() = 0;
};
class TaskScheduler {
std::queue<std::shared_ptr<Command>> tasks;
public:
void schedule(std::shared_ptr<Command> cmd) {
tasks.push(cmd);
}
};
Практическое применение
- Threading: Использую Monitor Object и Active Object для синхронизации
- Memory Management: RAII как основной паттерн управления ресурсами
- Network: Builder для конфигурации сокетов, Chain of Responsibility для обработки пакетов
- Database: Repository для абстракции доступа к БД, Unit of Work для транзакций
Ключевой момент — правильный выбор паттерна зависит от контекста. Переприменение паттернов ведёт к усложнению кода. Лучше начать с простого решения и рефакторить при необходимости.