Образец прототипа

В соответствии с шаблоном прототипа википедии: шаблон прототипа — это творческий шаблон проектирования, используемый при разработке программного обеспечения, когда тип создаваемых объектов определяется прототипом, который клонируется для создания новых объектов. Этот шаблон используется для:

  1. Избегайте подклассов создателя объекта в клиентском приложении, как это делает шаблон абстрактной фабрики.

  2. Избегайте неотъемлемых затрат на создание нового объекта стандартным способом (например, с использованием ключевого слова new), когда это непомерно дорого для данного приложения.


Я видел определенные демонстрационные коды этого шаблона на С++, все они используют конструктор копирования. Может ли кто-нибудь объяснить, как применяется пункт номер два (в целом, а также в контексте C ++), поскольку мы все равно используем конструктор копирования в функции клонирования. Если это можно сделать без конструктора копирования, то пример фрагмента кода был бы замечательным.


person user1017860    schedule 30.07.2012    source источник
comment
Клонирование по определению предполагает копирование, поэтому единственный способ не задействовать ни конструктор копирования, ни оператор присваивания — это иметь специальную функцию, которая копирует все поля вручную. Хотя это может вызвать конструкторы копирования полей.   -  person Some programmer dude    schedule 30.07.2012


Ответы (3)


Вы можете копировать без динамического размещения. Например, вот клонирование, которое происходит только в локальной области:

Foo prototype;

void local()
{
    Foo x = prototype; // first copy
    x.mutate();
    Foo y = x;         // another copy
}

Никогда не используется динамическое распределение.

Это правда, что return new Foo(*this); также создает копию, но что более важно, так это то, что этот объект выделяется динамически. Это стоимость, на которую ссылается ваша статья.

person Kerrek SB    schedule 30.07.2012

В игре, которую я делал на Java, я столкнулся с интересной ситуацией, которая вполне соответствовала требованиям шаблона прототипа. Видите ли, у меня был этот объект Animation, в котором хранился контейнер изображений для пролистывания, а также некоторые другие данные, которые отслеживали, сколько времени прошло с момента рендеринга последнего кадра, в каком кадре он был, выполнялась анимация или нет и т. д. .

Я обнаружил, что использование одним и тем же объектом анимации несколькими персонажами вызывало проблемы. Если бы у двух персонажей была общая анимация, они бы включали и выключали анимацию в конфликтующие друг с другом моменты времени. Я бы хотел, чтобы ребята стояли на месте с анимацией ходьбы или двигались с анимацией стоя. Создание объектов анимации было дорогостоящим и отнимало много времени, включая создание спрайтов, настройку количества времени, в течение которого они будут отображаться, создание интервальной очереди изображений и т. д.

Вместо этого я сделал объект Animation объектом-прототипом. Если анимация клонирует себя, она разделяет исходную коллекцию кадров со всеми другими анимациями, поскольку они неизменяемы, но их создание требует больших затрат. Вместо этого новые объекты будут использовать эту неизменную базу, но иметь собственную информацию о том, какой кадр рисовать и когда.

Думайте об этом как о проекторе. Когда его клонируют, новый проектор может иметь свою собственную информацию о том, работает он или нет, в каком кадре он находится и т. Д., Но он может использовать тот же кусок пленки, что и исходный проектор. Причина, по которой они не сбивают друг друга с толку, заключается в том, что фильм неизменен. (и дорого в создании)

Честно говоря, использование прототипа таким образом — отличный способ реализовать шаблон легковеса. Объекты, которые разделяют Объекты, которые дорого создавать. Если вы «клонируете» их, они будут созданы с их новым переходным состоянием, но по-прежнему будут делиться этими дорогостоящими базовыми объектами с их создателем.

person C0M37    schedule 21.12.2012

Вызов конструктора копирования для объекта, который не использует динамическую память внутри себя, намного быстрее, чем выполнение любого выделения в динамической памяти через new. Потому что выделение в динамической памяти — это своего рода системный вызов.

person inkooboo    schedule 30.07.2012