Назовите порождающие, структурные и поведенческие паттерны программирования и приведите примеры их использования.cplus-80

1. Порождающие паттерны

Singleton

Назначение: Гарантирует существование только одного экземпляра класса
Пример: Логгер, доступ к БД

class Database {
    static Database* instance;
    Database() {} // Приватный конструктор
public:
    static Database* getInstance() {
        if (!instance) instance = new Database();
        return instance;
    }
};
Database* Database::instance = nullptr;

Factory Method

Назначение: Делегирует создание объектов подклассам
Пример: Кросс-платформенные 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(); }
};

Builder

Назначение: Пошаговое создание сложных объектов
Пример: Построение 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 + ";"; }
};

2. Структурные паттерны

Adapter

Назначение: Преобразует интерфейс класса в другой интерфейс
Пример: Интеграция старого кода

class LegacyPrinter {
public:
    void printDocument() { /*...*/ }
};

class ModernPrinterInterface {
public:
    virtual void print() = 0;
};

class PrinterAdapter : public ModernPrinterInterface {
    LegacyPrinter legacyPrinter;
public:
    void print() override { legacyPrinter.printDocument(); }
};

Composite

Назначение: Единообразная работа с отдельными объектами и их композициями
Пример: Графические редакторы

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); }
};

Proxy

Назначение: Контроль доступа к объекту
Пример: Ленивая загрузка

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();
    }
};

3. Поведенческие паттерны

Observer

Назначение: Уведомление объектов об изменениях
Пример: 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);
    }
};

Strategy

Назначение: Инкапсуляция алгоритмов
Пример: Сортировка данных

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); }
};

Command

Назначение: Инкапсуляция запросов как объектов
Пример: История операций

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Управление алгоритмами и взаимодействиями

Резюмируем

  1. Порождающие паттерны решают проблемы создания объектов:

    • Singleton для глобального доступа
    • Factory для гибкого инстанцирования
    • Builder для сложных конфигураций
  2. Структурные паттерны организуют отношения между классами:

    • Adapter для интеграции несовместимых интерфейсов
    • Composite для древовидных структур
    • Proxy для контроля доступа
  3. Поведенческие паттерны определяют взаимодействие объектов:

    • Observer для событийной модели
    • Strategy для замены алгоритмов
    • Command для инкапсуляции операций

Выбор паттерна должен определяться конкретной задачей, а не желанием использовать "модный" паттерн. В 90% случаев достаточно простых решений.