Назначение: Гарантирует существование только одного экземпляра класса
Пример: Логгер, доступ к БД
class Database {
static Database* instance;
Database() {} // Приватный конструктор
public:
static Database* getInstance() {
if (!instance) instance = new Database();
return instance;
}
};
Database* Database::instance = nullptr;
Назначение: Делегирует создание объектов подклассам
Пример: Кросс-платформенные UI элементы
class Button {
public:
virtual void render() = 0;
};
class WindowsButton : public Button { /*...*/ };
class LinuxButton : public Button { /*...*/ };
class Dialog {
public:
virtual Button* createButton() = 0;
void render() { Button* btn = createButton(); btn->render(); }
};
Назначение: Пошаговое создание сложных объектов
Пример: Построение SQL-запросов
class QueryBuilder {
std::string query;
public:
QueryBuilder& select(const std::string& fields) {
query += "SELECT " + fields; return *this;
}
QueryBuilder& where(const std::string& condition) {
query += " WHERE " + condition; return *this;
}
std::string build() { return query + ";"; }
};
Назначение: Преобразует интерфейс класса в другой интерфейс
Пример: Интеграция старого кода
class LegacyPrinter {
public:
void printDocument() { /*...*/ }
};
class ModernPrinterInterface {
public:
virtual void print() = 0;
};
class PrinterAdapter : public ModernPrinterInterface {
LegacyPrinter legacyPrinter;
public:
void print() override { legacyPrinter.printDocument(); }
};
Назначение: Единообразная работа с отдельными объектами и их композициями
Пример: Графические редакторы
class Graphic {
public:
virtual void draw() = 0;
};
class Circle : public Graphic { /*...*/ };
class GraphicGroup : public Graphic {
std::vector<Graphic*> children;
public:
void draw() override {
for (auto child : children) child->draw();
}
void add(Graphic* g) { children.push_back(g); }
};
Назначение: Контроль доступа к объекту
Пример: Ленивая загрузка
class Image {
public:
virtual void display() = 0;
};
class RealImage : public Image { /*...*/ };
class ProxyImage : public Image {
RealImage* realImage = nullptr;
public:
void display() override {
if (!realImage) realImage = new RealImage();
realImage->display();
}
};
Назначение: Уведомление объектов об изменениях
Пример: Event системы
class Observer {
public:
virtual void update(const std::string& data) = 0;
};
class Subject {
std::vector<Observer*> observers;
public:
void attach(Observer* o) { observers.push_back(o); }
void notify(const std::string& data) {
for (auto o : observers) o->update(data);
}
};
Назначение: Инкапсуляция алгоритмов
Пример: Сортировка данных
class SortStrategy {
public:
virtual void sort(std::vector<int>&) = 0;
};
class QuickSort : public SortStrategy { /*...*/ };
class MergeSort : public SortStrategy { /*...*/ };
class Sorter {
SortStrategy* strategy;
public:
void setStrategy(SortStrategy* s) { strategy = s; }
void execute(std::vector<int>& data) { strategy->sort(data); }
};
Назначение: Инкапсуляция запросов как объектов
Пример: История операций
class Command {
public:
virtual void execute() = 0;
virtual void undo() = 0;
};
class TextEditor {
std::string text;
public:
void addText(const std::string& s) { text += s; }
// ...
};
class AddTextCommand : public Command {
TextEditor& editor;
std::string text;
public:
void execute() override { editor.addText(text); }
void undo() override { /*...*/ }
};
Категория | Паттерны | Основная цель |
---|---|---|
Порождающие | Singleton, Factory, Builder | Гибкое создание объектов |
Структурные | Adapter, Composite, Proxy | Организация структуры кода |
Поведенческие | Observer, Strategy, Command | Управление алгоритмами и взаимодействиями |
Порождающие паттерны решают проблемы создания объектов:
Структурные паттерны организуют отношения между классами:
Поведенческие паттерны определяют взаимодействие объектов:
Выбор паттерна должен определяться конкретной задачей, а не желанием использовать "модный" паттерн. В 90% случаев достаточно простых решений.