Паттерн 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++
⇑