Паттерн Prototype. Реализация схемы на C++
Содержание
- 1. Общие сведения. Назначение. Отношения
- 2. Применение
- 3. Участники паттерна. Пример программы на языке C++. Реализация структуры (рисунок 1)
- 4. Результаты
- 5. Реализация
- Связанные темы
Поиск на других ресурсах:
1. Общие сведения. Назначение. Отношения
Паттерн Prototype относится к паттернам, порождающим объекты. Паттерн позволяет создавать объекты разных типов с помощью объекта-прототипа. Этот объект возвращает копию конкретного объекта данного типа.
Структура паттерна Prototype изображена на рисунке 1.
Рисунок 1. Структура паттерна Prototype
Отношение: клиент запрашивает прототип, чтобы получить его копию.
⇑
2. Применение
Паттерн Prototype целесообразно применять в следующих случаях.
- Когда создание и представление конечных продуктов не влияет на систему в целом.
- Экземпляры классов продуктов должны быть определены на этапе выполнения с помощью полиморфизма.
- Когда есть лишним создание иерархий классов или их фабрик, которые параллельны к иерархии классов-продуктов.
- Если нужно, чтобы объект класса мог находиться в одном из нескольких разных состояний. В этом случае создается соответствующее количество прототипов и реализуется их клонирование.
⇑
3. Участники паттерна. Пример программы на языке C++. Реализация структуры (рисунок 1)
В примере реализован паттерн Prototype, структура которого изображена на рисунке 1.
Участниками паттерна являются следующие классы:
- Prototype – задает интерфейс для клонирования самого себя;
- ConcretePrototype – реализует операцию (метод) клонирования себя;
- Client – с помощью прототипа (prototype) задает запрос на создание нового объекта для клонирования самого себя. В программе клиентом выступает функция main().
#include <iostream> using namespace std; // Паттерн Prototype - реализация структуры // Абстрактный класс прототипа, // подклассы этого класса будут клонировать сами себя class Prototype abstract { public: virtual Prototype* Clone() abstract; // Дополнительный метод вывода информации о классе virtual void Print(string) abstract; }; // Классы конкретных прототипов // Конкретный прототип 1 class ConcretePrototype1 : public Prototype { private: string data; // данные класса public: // Конструктор ConcretePrototype1(string data) : data(data) { } Prototype* Clone() override { // Создать копию в памяти Prototype* p = new ConcretePrototype1(data); // Вернуть копию return p; } // Метод вывода информации о классе void Print(string msg) override { cout << msg << " => " << data << endl; } }; // Конкретный прототип 2 class ConcretePrototype2 : public Prototype { private: string data; // данные класса public: // Конструктор ConcretePrototype2(string data) : data(data) { } // Метод клонирования virtual Prototype* Clone() override { // Создать копию в памяти Prototype* p = new ConcretePrototype2(data); // Вернуть копию return p; } // Метод вывода информации о классе void Print(string msg) override { cout << msg << " => " << data << endl; } }; void main() { // Клиентский код // Ввести номер класса-прототипа int numPrototype; cout << "numPrototype = "; cin >> numPrototype; Prototype* p = nullptr; // В зависимости от numPrototype получить соответствующую копию if (numPrototype == 1) { // Создать объект прототипа ConcretePrototype1 prototype1("prototype1"); // Получить копию p = prototype1.Clone(); } else { // Создать объект прототипа ConcretePrototype2 prototype2("prototype2"); p = prototype2.Clone(); } // Вивести информацию об объекте прототипе p->Print("p"); // Освободить ранее выделенную память if (p) delete p; }
⇑
4. Результаты
Результаты использования паттерна Prototype дают следующие преимущества:
- паттерн скрывает от клиента конкретные классы продуктов. Это уменьшает количество имен, известных клиенту;
- паттерн дает возможность клиенту работать с узкоспециализированными классами без дополнительных модификаций;
- добавление и удаление продуктов может происходить во время выполнения. Здесь у клиента появляется дополнительная гибкость по сравнению с другими порождающими паттернами;
- новые объекты создаются за счет изменения их поведения (изменение значений переменных объекта), а не за счет определения новых классов. Иными словами, на основе уже существующих классов создаются экземпляры новых видов клиентских объектов;
- существует возможность определения новых объектов путем изменения структуры. Это построение объектов из разных составляющих с помощью клонирования;
- уменьшение количества подклассов по сравнению с другими паттернами (Factory Method, Abstract Factory);
- с помощью классов происходит динамическое конфигурирование приложения. Классы подгружаются в приложение во время выполнения.
Недостатком паттерна считается сложность реализации Clone() в некоторых случаях. Примером может служить наличие других подобъектов в данном объекте.
⇑
5. Реализация
При реализации паттерна Prototype можно выделить следующие главные вопросы.
- Использование диспетчера прототипов. Здесь имеется в виду ведение реестра прототипов для использования клиентами. Клиенты хранят прототипы в реестре и извлекают их из него на основе заданного ключа.
- Сложность реализации метода Clone() в случае, если объект является сложной структурой с циклическими ссылками. Здесь важно выполнить глубокое копирование элементов, входящих в структуру сложного объекта. При этом следует учитывать такую же последовательность шагов при освобождении копии объекта.
- Инициализация клона значениями. Здесь возможны ситуации, когда для разных клонированных объектов нужно получать разные значения параметров.
⇑
Связанные темы
- Паттерн Abstract Factory. Решение задачи о составляющих компьютера
- Обзор и исследование. Реализация на C++
- Паттерн Factory Method. Реализация структуры на C++
- Паттерн Singleton. Обзор. Особенности применения. Реализация на C++
⇑