Прототип (англ. Prototype) — твірний шаблон проєктування, який дозволяє створювати копії існуючих об'єктів таким чином, що програмний код не залежить від їх класів.
Цей шаблон застосовують у випадку, коли тип об'єктів, що створюються заданий екземпляром прототипу, що використовується для створення нових об'єктів шляхом копіювання цього прототипу. Він використовується для:
- уникнення успадкування класу, що створює ці об'єкти в клієнтському застосуванні, як це відбувається при використанні фабричного методу.
- уникнення витрат, що виникають при створенні нових об'єктів стандартним способом (тобто при використанні ключового слова ''), коли це може бути занадто марнотратно для даного застосування.
Для реалізації цього шаблону, необхідно визначити абстрактний базовий клас (інтерфейс), який визначає чисто віртуальний метод clone(). Будь-який клас, що потребує виконання функціоналу «поліморфного конструктора» буде успадковувати цей базовий абстрактний клас, і реалізовувати операцію clone().
Клієнт, замість того, щоб писати код, який би використовував оператор «new» із жорстко вказаним іменем класу, викликає метод clone() для прототипу.
Прикладом ситуації, що демонструє шаблон Прототип є мітотичний поділ живих клітин — що призводить до створення двох ідентичних клітин — тут прототип відіграє важливу роль в створенні повної копії самого себе. Коли відбувається ділення клітини, в результаті утворюються дві ідентичні клітини із ідентичним генотипом. Іншими словами, клітина клонує сама себе.
Опис
Шаблон проектування Прототип є одним із двадцяти трьох добре відомих шаблонів, із книги Банди чотирьох (GoF) який описує як вирішити рекурсивні задачі проектування, для створення гнучкого і придатного для повторного використання об'єктно-орієнтованого програмного забезпечення, у такий спосіб, щоб об'єкти було легше реалізовувати, змінювати, тестувати, і повторно використовувати.
Призначення
Задає види об'єктів, що створюються, за допомогою екземпляру-прототипу, та створює нові об'єкти шляхом копіювання цього прототипу.
Шаблон проектування Прототип дозволяє вирішити такі проблеми як:
- Як об'єкти можуть створюватися у такий спосіб?, що те, який об'єкт буде створено може бути визначено під час виконання коду?
- Як можна створити екземпляри динамічно завантажених об'єктів?
Створення нових об'єктів напряму за допомогою класу, що потребує (використовує) певні об'єкти є не достатньо гнучким, оскільки змушує прив'язати клас до певних об'єктів під час компіляції, і стає неможливо визначити які об'єкти будуть створені під час виконання коду.
Шаблон проектування прототип визначає спосіб, як вирішити цю задачу:
- Визначити об'єкт
Prototype
(прототип), що створює копію самого себе. - Створити новий об'єкт шляхом копіювання об'єкту
Prototype
.
Це дозволяє створювати конфігурації класу із різними об'єктами прототипу Prototype
, які будуть копіюватися для створення нових об'єктів, і навіть більше, об'єкти Prototype
можуть додаватися і знищуватися під час виконання.
Застосування
Слід використовувати шаблон Прототип коли:
- класи, що інстанціюються, визначаються під час виконання, наприклад за допомогою динамічного завантаження;
- треба запобігти побудові ієрархій класів або фабрик, паралельних ієрархій класів продуктів;
- екземпляри класу можуть знаходитись у одному з не дуже великої кількості станів. Може статися, що зручніше встановити відповідну кількість прототипів та клонувати їх, а не інстанціювати щоразу клас вручну в слушному стані.
Емпіричні правила
Іноді твірні шаблони збігаються один з одним — існують випадки, коли більш доречно використовувати або прототип або абстрактну фабрику. А в інших випадках вони доповнюють один одного: абстрактна фабрика може зберігати множину прототипів, з яких буде створюватися копія і повертатимуться утворені об'єкти (GoF, с. 126). Абстрактна фабрика, будівник, і прототип можуть в своїй реалізації використовувати шаблон Одинак. (GoF, сc. 81, 134). Класи абстрактних фабрик часто реалізовані за допомогою фабричних методів (створення через успадкування), але вони можуть також реалізовуватися за допомогою прототипу (створення шляхом [en]). (GoF, с.95)
Часто, проектування починається із використання фабричного методу (менш складно, піддається кращому налаштовуванню, поширюється на підкласи) і еволюціонує в сторону абстрактної фабрики, прототипу, або будівника (більш гнучкі і більш складні) якщо архітектор коду виявляє де потребується більша гнучкість поведінки. (GoF, с.136)
Прототип не потребує створення підкласів, але потребує процедури «ініціалізації». Фабричний метод потребує створення підкласів, але не потребу ініціалізації. (GoF, с. 116)
Архітектури, які широко використовують шаблони компонувальник та декоратор, також можуть отримати вигоду із використання прототипу. (GoF, с.126)
Емпіричне правило може полягати в тому, що вам може знадобитися метод копіювання clone() Об'єкту коли ви хочете створити інший об'єкт під час виконання коду, який є повною копією того об'єкта, що ви копіюєте. Повна копія означає, що всі атрибути новоствореного об'єкту будуть такими ж самими, як і в того об'єкта який ви клонуєте. Якби замість цього ви створювали екземпляр даного класу використовуючи ключове слово new, ви б отримали об'єкт із атрибутами, що мають початкові не задані значення.
Наприклад, якщо ви використовуєте систему, що здійснює транзакції із банківським рахунком, тобі б вам знадобилося створити копію об'єкту, що зберігає в собі інформацію про цей рахунок, здійснити над ним транзакцію, а потім замінити оригінальний об'єкт на змінений. В даному випадку ви б захотіли використати метод clone() замість new.
Структура
- Prototype — прототип:
- визначає інтерфейс для клонування самого себе;
- ConcretePrototype — конкретний прототип:
- реалізує операцію клонування самого себе;
- Client — клієнт:
- створює новий об'єкт, звертаючись до прототипу із запитом клонувати себе.
Переваги
- Створює глибоку копію комплексної ієрархії об'єктів
- Зменшення навантаження ініціалізації
- Багаторазові можливості — оптимізовані зусилля щодо кодування
- Спрощений процес копіювання об'єктів:
Недоліки
- Додаткові витрати на розробку
- Потребує уважності і точності при глибокому копіюванні
Відносини
Клієнт звертається до прототипу, щоб той створив свого клона.
Реалізація
Приклад С++
#include <iostream> #include <string> #include <vector> using namespace std; struct Prototype { virtual Prototype* Clone() = 0; }; class Item : public Prototype { public: int ID; string Name; public: Item(string strName) : Name(strName) { ID = GetNewID(); }; // конструктор копіювання Item(Item& item) : Name(item.Name) { ID = GetNewID(); }; virtual ~Item() { }; virtual Prototype* Clone() { return new Item(*this); }; static int GetNewID() { static int ID = 0; return ++ID; }; }; void print(Prototype* p) { Item* pItem = dynamic_cast <Item*> (p); cout << "ID: " << pItem->ID << endl; cout << "Name: " << pItem->Name << endl; cout << endl; } void main() { vector<Prototype*> items; Item Item("Concrete Item"); // клонуємо об'єкт for (int i = 0; i < 10; ++i) { items.push_back ( Item.Clone() // виклик методу клонування ); } // Друкуємо клонів for (int i = 0; i < 10; ++i) { print(items[i]); } }
Приклад С#
using System; using System.IO; using System.Drawing; using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; namespace PrototypePattern { static class Prototype { public static T DeepCopy<T>(this T self) { var formatter = new BinaryFormatter(); using (var memoryStream = new MemoryStream()) { formatter.Serialize(memoryStream, self); memoryStream.Seek(0, SeekOrigin.Begin); var clone = formatter.Deserialize(memoryStream); return (T)clone; } } } [Serializable] class TreePrefab { private int _height; private Color _color; public TreePrefab(int height, Color color) { _height = height; _color = color; } public void SetColor(Color color) { _color = color; } } class Program { static void Main(string[] args) { var treePrefab = new TreePrefab(2, Color.Green); var forest = new List<TreePrefab>(); for (int i = 0; i < 10; i++) { var tree = treePrefab.DeepCopy(); tree.SetColor(i % 2 == 0 ? Color.Green : Color.YellowGreen); forest.Add(tree); } } } }
Примітки
- Duell, Michael (July 1997). Non-Software Examples of Design Patterns. Object Magazine. 7 (5): 54. ISSN 1055-3614.
- Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison Wesley. с. 117ff. ISBN .
- . w3sDesign.com. Архів оригіналу за 18 серпня 2017. Процитовано 17 серпня 2017.
Джерела
- Design Patterns: Elements of Reusable Object-Oriented Software [ 9 листопада 2012 у Wayback Machine.]
Література
Алан Шаллоуей, Джеймс Р. Тротт. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М. : «Вильямс», 2002. — 288 с. — .
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Prototip angl Prototype tvirnij shablon proyektuvannya yakij dozvolyaye stvoryuvati kopiyi isnuyuchih ob yektiv takim chinom sho programnij kod ne zalezhit vid yih klasiv Cej shablon zastosovuyut u vipadku koli tip ob yektiv sho stvoryuyutsya zadanij ekzemplyarom prototipu sho vikoristovuyetsya dlya stvorennya novih ob yektiv shlyahom kopiyuvannya cogo prototipu Vin vikoristovuyetsya dlya uniknennya uspadkuvannya klasu sho stvoryuye ci ob yekti v kliyentskomu zastosuvanni yak ce vidbuvayetsya pri vikoristanni fabrichnogo metodu uniknennya vitrat sho vinikayut pri stvorenni novih ob yektiv standartnim sposobom tobto pri vikoristanni klyuchovogo slova new koli ce mozhe buti zanadto marnotratno dlya danogo zastosuvannya Dlya realizaciyi cogo shablonu neobhidno viznachiti abstraktnij bazovij klas interfejs yakij viznachaye chisto virtualnij metod clone Bud yakij klas sho potrebuye vikonannya funkcionalu polimorfnogo konstruktora bude uspadkovuvati cej bazovij abstraktnij klas i realizovuvati operaciyu clone Kliyent zamist togo shob pisati kod yakij bi vikoristovuvav operator new iz zhorstko vkazanim imenem klasu viklikaye metod clone dlya prototipu Prikladom situaciyi sho demonstruye shablon Prototip ye mitotichnij podil zhivih klitin sho prizvodit do stvorennya dvoh identichnih klitin tut prototip vidigraye vazhlivu rol v stvorenni povnoyi kopiyi samogo sebe Koli vidbuvayetsya dilennya klitini v rezultati utvoryuyutsya dvi identichni klitini iz identichnim genotipom Inshimi slovami klitina klonuye sama sebe OpisShablon proektuvannya Prototip ye odnim iz dvadcyati troh dobre vidomih shabloniv iz knigi Bandi chotiroh GoF yakij opisuye yak virishiti rekursivni zadachi proektuvannya dlya stvorennya gnuchkogo i pridatnogo dlya povtornogo vikoristannya ob yektno oriyentovanogo programnogo zabezpechennya u takij sposib shob ob yekti bulo legshe realizovuvati zminyuvati testuvati i povtorno vikoristovuvati Priznachennya Zadaye vidi ob yektiv sho stvoryuyutsya za dopomogoyu ekzemplyaru prototipu ta stvoryuye novi ob yekti shlyahom kopiyuvannya cogo prototipu Shablon proektuvannya Prototip dozvolyaye virishiti taki problemi yak Yak ob yekti mozhut stvoryuvatisya u takij sposib sho te yakij ob yekt bude stvoreno mozhe buti viznacheno pid chas vikonannya kodu Yak mozhna stvoriti ekzemplyari dinamichno zavantazhenih ob yektiv Stvorennya novih ob yektiv napryamu za dopomogoyu klasu sho potrebuye vikoristovuye pevni ob yekti ye ne dostatno gnuchkim oskilki zmushuye priv yazati klas do pevnih ob yektiv pid chas kompilyaciyi i staye nemozhlivo viznachiti yaki ob yekti budut stvoreni pid chas vikonannya kodu Shablon proektuvannya prototip viznachaye sposib yak virishiti cyu zadachu Viznachiti ob yekt Prototype prototip sho stvoryuye kopiyu samogo sebe Stvoriti novij ob yekt shlyahom kopiyuvannya ob yektu Prototype Ce dozvolyaye stvoryuvati konfiguraciyi klasu iz riznimi ob yektami prototipu Prototype yaki budut kopiyuvatisya dlya stvorennya novih ob yektiv i navit bilshe ob yekti Prototype mozhut dodavatisya i znishuvatisya pid chas vikonannya Zastosuvannya Slid vikoristovuvati shablon Prototip koli klasi sho instanciyuyutsya viznachayutsya pid chas vikonannya napriklad za dopomogoyu dinamichnogo zavantazhennya treba zapobigti pobudovi iyerarhij klasiv abo fabrik paralelnih iyerarhij klasiv produktiv ekzemplyari klasu mozhut znahoditis u odnomu z ne duzhe velikoyi kilkosti staniv Mozhe statisya sho zruchnishe vstanoviti vidpovidnu kilkist prototipiv ta klonuvati yih a ne instanciyuvati shorazu klas vruchnu v slushnomu stani Empirichni pravila Inodi tvirni shabloni zbigayutsya odin z odnim isnuyut vipadki koli bilsh dorechno vikoristovuvati abo prototip abo abstraktnu fabriku A v inshih vipadkah voni dopovnyuyut odin odnogo abstraktna fabrika mozhe zberigati mnozhinu prototipiv z yakih bude stvoryuvatisya kopiya i povertatimutsya utvoreni ob yekti GoF s 126 Abstraktna fabrika budivnik i prototip mozhut v svoyij realizaciyi vikoristovuvati shablon Odinak GoF sc 81 134 Klasi abstraktnih fabrik chasto realizovani za dopomogoyu fabrichnih metodiv stvorennya cherez uspadkuvannya ale voni mozhut takozh realizovuvatisya za dopomogoyu prototipu stvorennya shlyahom en GoF s 95 Chasto proektuvannya pochinayetsya iz vikoristannya fabrichnogo metodu mensh skladno piddayetsya krashomu nalashtovuvannyu poshiryuyetsya na pidklasi i evolyucionuye v storonu abstraktnoyi fabriki prototipu abo budivnika bilsh gnuchki i bilsh skladni yaksho arhitektor kodu viyavlyaye de potrebuyetsya bilsha gnuchkist povedinki GoF s 136 Prototip ne potrebuye stvorennya pidklasiv ale potrebuye proceduri inicializaciyi Fabrichnij metod potrebuye stvorennya pidklasiv ale ne potrebu inicializaciyi GoF s 116 Arhitekturi yaki shiroko vikoristovuyut shabloni komponuvalnik ta dekorator takozh mozhut otrimati vigodu iz vikoristannya prototipu GoF s 126 Empirichne pravilo mozhe polyagati v tomu sho vam mozhe znadobitisya metod kopiyuvannya clone Ob yektu koli vi hochete stvoriti inshij ob yekt pid chas vikonannya kodu yakij ye povnoyu kopiyeyu togo ob yekta sho vi kopiyuyete Povna kopiya oznachaye sho vsi atributi novostvorenogo ob yektu budut takimi zh samimi yak i v togo ob yekta yakij vi klonuyete Yakbi zamist cogo vi stvoryuvali ekzemplyar danogo klasu vikoristovuyuchi klyuchove slovo new vi b otrimali ob yekt iz atributami sho mayut pochatkovi ne zadani znachennya Napriklad yaksho vi vikoristovuyete sistemu sho zdijsnyuye tranzakciyi iz bankivskim rahunkom tobi b vam znadobilosya stvoriti kopiyu ob yektu sho zberigaye v sobi informaciyu pro cej rahunok zdijsniti nad nim tranzakciyu a potim zaminiti originalnij ob yekt na zminenij V danomu vipadku vi b zahotili vikoristati metod clone zamist new StrukturaUML diagrama sho opisuye strukturu shablonu proyektuvannya Prototip Prototype prototip viznachaye interfejs dlya klonuvannya samogo sebe ConcretePrototype konkretnij prototip realizuye operaciyu klonuvannya samogo sebe Client kliyent stvoryuye novij ob yekt zvertayuchis do prototipu iz zapitom klonuvati sebe PerevagiStvoryuye gliboku kopiyu kompleksnoyi iyerarhiyi ob yektiv Zmenshennya navantazhennya inicializaciyi Bagatorazovi mozhlivosti optimizovani zusillya shodo koduvannya Sproshenij proces kopiyuvannya ob yektiv NedolikiDodatkovi vitrati na rozrobku Potrebuye uvazhnosti i tochnosti pri glibokomu kopiyuvanniVidnosiniKliyent zvertayetsya do prototipu shob toj stvoriv svogo klona RealizaciyaPriklad S Priklad realizaciyi movoyu S include lt iostream gt include lt string gt include lt vector gt using namespace std struct Prototype virtual Prototype Clone 0 class Item public Prototype public int ID string Name public Item string strName Name strName ID GetNewID konstruktor kopiyuvannya Item Item amp item Name item Name ID GetNewID virtual Item virtual Prototype Clone return new Item this static int GetNewID static int ID 0 return ID void print Prototype p Item pItem dynamic cast lt Item gt p cout lt lt ID lt lt pItem gt ID lt lt endl cout lt lt Name lt lt pItem gt Name lt lt endl cout lt lt endl void main vector lt Prototype gt items Item Item Concrete Item klonuyemo ob yekt for int i 0 i lt 10 i items push back Item Clone viklik metodu klonuvannya Drukuyemo kloniv for int i 0 i lt 10 i print items i Priklad S Priklad realizaciyi movoyu S using System using System IO using System Drawing using System Collections Generic using System Runtime Serialization Formatters Binary namespace PrototypePattern static class Prototype public static T DeepCopy lt T gt this T self var formatter new BinaryFormatter using var memoryStream new MemoryStream formatter Serialize memoryStream self memoryStream Seek 0 SeekOrigin Begin var clone formatter Deserialize memoryStream return T clone Serializable class TreePrefab private int height private Color color public TreePrefab int height Color color height height color color public void SetColor Color color color color class Program static void Main string args var treePrefab new TreePrefab 2 Color Green var forest new List lt TreePrefab gt for int i 0 i lt 10 i var tree treePrefab DeepCopy tree SetColor i 2 0 Color Green Color YellowGreen forest Add tree PrimitkiDuell Michael July 1997 Non Software Examples of Design Patterns Object Magazine 7 5 54 ISSN 1055 3614 Erich Gamma Richard Helm Ralph Johnson John Vlissides 1994 Design Patterns Elements of Reusable Object Oriented Software Addison Wesley s 117ff ISBN 0 201 63361 2 w3sDesign com Arhiv originalu za 18 serpnya 2017 Procitovano 17 serpnya 2017 DzherelaDesign Patterns Elements of Reusable Object Oriented Software 9 listopada 2012 u Wayback Machine LiteraturaAlan Shallouej Dzhejms R Trott Shablony proektirovaniya Novyj podhod k obektno orientirovannomu analizu i proektirovaniyu Design Patterns Explained A New Perspective on Object Oriented Design M Vilyams 2002 288 s ISBN 0 201 71594 5