stringtranslate.com

Прототипный образец

Шаблон прототипа — это шаблон проектирования создания в разработке программного обеспечения . Он используется, когда типы создаваемых объектов определяются прототипическим экземпляром , который клонируется для создания новых объектов. Этот шаблон используется для того, чтобы избежать подклассов создателя объекта в клиентском приложении, как это делает шаблон метода фабрики , и избежать неотъемлемых затрат на создание нового объекта стандартным способом (например, с использованием ключевого слова ' new '), когда это непозволительно дорого для данного приложения.

Для реализации шаблона клиент объявляет абстрактный базовый класс , который определяет чистый виртуальный метод clone() . Любой класс, которому нужна возможность « полиморфного конструктора », выводится из абстрактного базового класса и реализует операцию clone() .

Клиент, вместо написания кода, который вызывает оператор «new» для жестко закодированного имени класса, вызывает метод clone() для прототипа, вызывает фабричный метод с параметром, обозначающим конкретный требуемый производный класс , или вызывает метод clone() через некий механизм, предоставляемый другим шаблоном проектирования.

Митотическое деление клетки, приводящее к двум идентичным клеткам, является примером прототипа, который играет активную роль в копировании самого себя и, таким образом, демонстрирует модель Прототипа. Когда клетка делится, в результате получаются две клетки с идентичным генотипом. Другими словами, клетка клонирует себя. [1]

Обзор

Шаблон проектирования прототипа — один из 23 шаблонов проектирования «Банды четырех» , которые описывают, как решать повторяющиеся проблемы проектирования для разработки гибкого и повторно используемого объектно-ориентированного программного обеспечения, то есть объектов, которые легче внедрять, изменять, тестировать и повторно использовать. [2] : 117 

Шаблон проектирования прототипа решает такие проблемы, как: [3]

Создание объектов непосредственно внутри класса, который требует (использует) объекты, негибко, поскольку привязывает класс к определенным объектам во время компиляции и делает невозможным указание того, какие объекты создавать во время выполнения.

Шаблон проектирования прототипа описывает, как решать такие проблемы:

Это позволяет конфигурировать класс с различными Prototypeобъектами, которые копируются для создания новых объектов, и даже больше, Prototypeобъекты могут быть добавлены и удалены во время выполнения.
См. также класс UML и диаграмму последовательности ниже.

Структура

Диаграмма классов и последовательностей UML

Пример класса UML и диаграммы последовательности для шаблона проектирования «Прототип».

В приведенной выше диаграмме классов UML класс ссылается на интерфейс для клонирования a . Класс реализует интерфейс, создавая копию самого себя. Диаграмма последовательности UML показывает взаимодействия во время выполнения: Объект вызывает объект , который создает и возвращает копию самого себя ( объект).ClientPrototypeProductProduct1Prototype
Clientclone()prototype:Product1product:Product1

Диаграмма классов UML

Диаграмма классов UML , описывающая шаблон проектирования прототипа

Практические правила

Иногда шаблоны создания перекрываются — есть случаи, когда либо прототип, либо абстрактная фабрика были бы уместны. В других случаях они дополняют друг друга: абстрактная фабрика может хранить набор прототипов, из которых можно клонировать и возвращать объекты продукта. [2] : 126  Абстрактные фабрика, строитель и прототип могут использовать синглтон в своих реализациях. [2] : 81, 134  Абстрактные классы фабрики часто реализуются с помощью методов фабрики (создание через наследование ), но их можно реализовать с помощью прототипа (создание через делегирование ). [2] : 95 

Часто проекты начинаются с использования метода Factory (менее сложный, более настраиваемый, подклассы разрастаются) и развиваются в сторону абстрактной фабрики, прототипа или конструктора (более гибкий, более сложный) по мере того, как проектировщик обнаруживает, где требуется больше гибкости. [2] : 136 

Прототип не требует подклассификации, но требует операции «инициализации». Метод-фабрика требует подклассификации, но не требует инициализации. [2] : 116 

Проекты, в которых активно используются композитные и декораторские шаблоны, также могут выиграть от использования Prototype. [2] : 126 

Общее руководство в программировании предлагает использовать clone()метод при создании дубликата объекта во время выполнения, чтобы гарантировать, что он точно отражает исходный объект. Этот процесс, известный как клонирование объекта, создает новый объект с идентичными атрибутами клонируемого объекта. В качестве альтернативы, создание экземпляра класса с использованием newключевого слова создает объект со значениями атрибутов по умолчанию.

Например, в контексте проектирования системы управления транзакциями по банковским счетам может потребоваться дублировать объект, содержащий информацию по счету, для проведения транзакций с сохранением исходных данных. В таких сценариях использование clone()метода предпочтительнее, чем использование newдля создания нового объекта.

Пример

Пример С++11

Эта реализация C++11 основана на реализации до C++98 в книге. Обсуждение шаблона проектирования вместе с полным иллюстративным примером реализации с использованием полиморфного проектирования классов приведены в аннотациях C++.

#include <iostream> enum Направление { Север , Юг , Восток , Запад };     класс MapSite { public : virtual void enter () = 0 ; virtual MapSite * clone () const = 0 ; virtual ~ MapSite () = default ; };                 class Room : public MapSite { public : Room () : roomNumber ( 0 ) {} Room ( int n ) : roomNumber ( n ) {} void setSide ( Direction d , MapSite * ms ) { std :: cout << "Room::setSide" << d << ' ' << ms << '\n' ; } virtual void enter () {} virtual Room * clone () const { // реализует операцию для клонирования себя. return new Room ( * this ); } Room & Operator = ( const Room & ) = delete ; private : int roomNumber ; };                                                   класс Стена : public MapSite { public : Стена () {} virtual void enter () {} virtual Стена * clone () const { return new Стена ( * this ); } };                    class Door : public MapSite { public : Door ( Room * r1 = nullptr , Room * r2 = nullptr ) : room1 ( r1 ), room2 ( r2 ) {} Door ( const Door & other ) : room1 ( other . room1 ), room2 ( other . room2 ) {} virtual void enter () {} virtual Door * clone () const { return new Door ( * this ); } virtual void initialize ( Room * r1 , Room * r2 ) { room1 = r1 ; room2 = r2 ; } Door & Operator = ( const Door & ) = delete ; private : Room * room1 ; Room * room2 ; };                                                          class Maze { public : void addRoom ( Room * r ) { std :: cout << "Maze::addRoom " << r << '\n' ; } Room * roomNo ( int ) const { return nullptr ; } virtual Maze * clone () const { return new Maze ( * this ); } virtual ~ Maze () = default ; };                                  класс MazeFactory { public : MazeFactory () = default ; virtual ~ MazeFactory () = default ;          виртуальный лабиринт * makeMaze () const { return new лабиринт ; } виртуальная стена * makeWall () const { return new стена ; } виртуальная комната * makeRoom ( int n ) const { return new комната ( n ); } виртуальная дверь * makeDoor ( комната * r1 , комната * r2 ) const { return new дверь ( r1 , r2 ); } };                                        class MazePrototypeFactory : public MazeFactory { public : MazePrototypeFactory ( Maze * m , Wall * w , Room * r , Door * d ) : prototypeMaze ( m ), prototypeRoom ( r ), prototypeWall ( w ), prototypeDoor ( d ) {} virtual Maze * makeMaze () const { // создает новый объект, запрашивая у прототипа клонирование самого себя. return prototypeMaze -> clone (); } virtual Room * makeRoom ( int ) const { return prototypeRoom -> clone (); } virtual Wall * makeWall () const { return prototypeWall -> clone (); } virtual Door * makeDoor ( Room * r1 , Room * r2 ) const { Door * door = prototypeDoor -> clone (); door -> initialize ( r1 , r2 ); return door ; } MazePrototypeFactory ( const MazePrototypeFactory & ) = delete ; MazePrototypeFactory & оператор = ( const MazePrototypeFactory & ) = delete ; частный : Лабиринт * prototypeMaze ; Комната * prototypeRoom ; Стена * prototypeWall ; Дверь * prototypeDoor ; };                                                                             // Если createMaze параметризован различными прототипическими объектами комнаты, двери и стены, которые он затем копирует и добавляет в лабиринт, то вы можете изменить состав лабиринта, заменив эти прототипические объекты другими. Это пример шаблона Prototype (133).класс MazeGame { public : Maze * createMaze ( MazePrototypeFactory & m ) { Maze * aMaze = m . сделать лабиринт (); Комната * r1 = м . сделатьКомнату ( 1 ); Комната * r2 = м . сделатьКомнату ( 2 ); Дверь * Дверь = м . сделатьДверь ( r1 , r2 ); aMaze -> addRoom ( r1 ); aMaze -> addRoom ( r2 ); r1 -> setSide ( North , m.makeWall () ) ; r1 -> setSide ( Восток , Дверь ); r1 -> setSide ( Юг , м . makeWall ()); r1 -> setSide ( West , m.makeWall () ) ; r2 -> setSide ( North , m.makeWall () ) ; r2 -> setSide ( Восток , м . makeWall ()); r2 -> setSide ( Юг , м . makeWall ()); r2 -> setSide ( Запад , Дверь ); вернуть лабиринт ; } };                                            int main () { MazeGame game ; MazePrototypeFactory simpleMazeFactory ( новый лабиринт , новая стена , новая комната , новая дверь ) ; game.createMaze ( simpleMazeFactory ) ; }              

Вывод программы:

Лабиринт :: addRoom 0x1160f50 Лабиринт :: addRoom 0x1160f70 Комната :: setSide 0 0x11613c0 Комната :: setSide 2 0x1160f90 Комната :: setSide 1 0x11613e0 Комната :: setSide 3 0x1161400 Комната :: setSide 0 0x1161420 Комната :: setSide 2 0x1161440 Комната :: setSide 1 0x1161460 Комната :: setSide 3 0x1160f90                  

Смотрите также

Ссылки

  1. ^ Дьюэлл, Майкл (июль 1997 г.). «Непрограммные примеры шаблонов проектирования». Object Magazine . 7 (5): 54. ISSN  1055-3614.
  2. ^ abcdefg Гамма, Эрих ; Хелм, Ричард; Джонсон, Ральф ; Влиссидес, Джон (1994). Шаблоны проектирования: элементы повторно используемого объектно-ориентированного программного обеспечения . Addison-Wesley. ISBN 0-201-63361-2.
  3. ^ "Шаблон проектирования прототипа - проблема, решение и применимость". w3sDesign.com . Получено 17 августа 2017 г.