Вопросы о шаблоне прототипа - PullRequest
40 голосов
/ 21 апреля 2011

Я узнаю о различных шаблонах дизайна, и у меня есть сильное ощущение, что мне не хватает важной части (или частей) для понимания этого конкретного шаблона.

На всех веб-сайтах, которые я просматривал и в GoFкнига, я вижу метод клонирования.Из того, что я понимаю, у нас есть некоторый тип объекта, который мы можем клонировать, когда нам нужны различные версии этого объекта, но мы не хотим вручную создавать каждый из них с помощью команды «new» (как в Java).Это может скрыть его конкретную реализацию.Поэтому, когда мы клонируем, мы можем немного подправить клон и сделать его тем, что нам нужно, без необходимости знать, как создать этот объект сложным способом.Правильно ли это мое мышление?

Мне также сказали, что это может уменьшить подклассы и впоследствии уменьшить количество классов, которые вам нужно сделать.Я не совсем понимаю эту часть.Может ли кто-нибудь помочь мне понять это?

Мой последний вопрос о шаблоне абстрактной фабрики (или даже фабричного метода).Эти фабричные шаблоны и шаблоны-прототипы чувствуют, что они пытаются скрыть конкретные реализации при создании новых объектов.Когда это хорошая идея, чтобы выбрать один из других?

Спасибо всем!

Ответы [ 3 ]

60 голосов
/ 21 апреля 2011

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

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

Пример

  • Дублирование DVD: Дублирование основного DVD для создания нескольких копий
  • Объект отчетности. Рассмотрим объект отчета, который содержит обработанную информацию для передачи в графический интерфейс. Исходный отчет содержит данные в порядке возрастания. Теперь, используя этот шаблон, можно создать аналогичный отчет, но с данными, отсортированными в порядке убывания.

Преимущества

  • Производительность: клонирование (с использованием MemberwiseClone ) значительно дешевле, чем создание нового объекта заново (с оператором new ). Обратите внимание, что нужно переопределить MemberwiseClose(), чтобы выполнить глубокое копирование.
  • Объекты могут быть клонированы очень динамично, без каких-либо настойчивых требований. Первый созданный объект может быть создан в любое время при выполнении приложения, и дальнейшее дублирование может иметь место в любое время вперед.

Когда его использовать

  • Когда классы для создания экземпляров указываются во время выполнения, например, динамической загрузкой.
  • Когда экземпляры класса могут иметь одну из нескольких различных комбинаций состояний. Может быть удобнее установить соответствующее количество прототипов и клонировать их, чем создавать экземпляр класса вручную, каждый раз с соответствующим состоянием.

Сравнение с заводским шаблоном

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

Но разница между этими двумя шаблонами заключается в том, что для Factory Method концентрируется на создании одного объекта несуществующего типа объекта как fresh creation (понимая точный подтип класса Creator). Шаблон Prototype использует сам класс, особенно производный класс для действия self duplication.


Шаблон фабричного метода

В этом шаблоне клиент (или потребитель) запрашивает Создателя (или фабрику) об определенном типе объекта из иерархии классов. Метод Creator класса фабрики делегирует создание конкретного объекта производным классам и возвращает объект класса того типа, который запрашивает клиент. По сути, у вас есть единая точка контакта для создания нескольких объектов иерархии классов.

Вы можете думать об этом как о том, что вы идете к счетчику авиабилетов (диспетчеру) и запрашиваете билет, указав предпочитаемый вами тип билета (первый класс, представительский или эконом). Пользователь не заботится о том, как генерируется билет, даже если в представлении объекта первый класс и билет эконом-класса получены из базового класса билета.

Когда использовать

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


Абстрактный фабричный рисунок

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

Определенный класс Factory уже существует. Но у Фабрики будут несколько разные методы. Каждый метод может создать экземпляр. Клиент может выбрать подходящий метод и получить экземпляр.

Если вы возьмете пример идеального архитектурного дизайна на основе MVC , клиент будет классом Business Controller, а все конкретные продукты - бизнес-объектами. Фабрики являются вспомогательными (вспомогательными) контроллерами. Они работают совместно с запросом от Business Controller.

Когда использовать

  • Ожидается, что система будет независима от того, как создаются продукты. Можно даже ожидать независимости от того, как продукты составлены и представлены. Термин «продукт» применяется к конечному получающемуся объекту, который разработчик клиента должен будет использовать, вызывая его методы.
  • Система, которая должна конфигурироваться с одним из нескольких семейств продуктов. Таким образом, фактический выбор семейства будет не во время кодирования, а во время более позднего конфигурирования.
  • Семейство продуктов предназначено для совместной работы.
  • Создание для библиотеки продуктов. Больше всего здесь волнует соответствующий интерфейс, а не реализация.
27 голосов
/ 21 апреля 2011

Судя по всему, у вас есть образец прототипа.

Как это сокращает подклассы

Допустим, вы делаете MineCraft и используете шаблон-прототип для каждого типа блоков (например, грязь, камень и т. Д.).Все объекты-прототипы на самом деле принадлежат к одному и тому же классу Block, но для каждого объекта установлены разные свойства, поэтому он выглядит и ведет себя по-разному, например:

prototypes.dirt = new Block;
prototypes.dirt.texture = new Image("dirt.jpg");
prototypes.dirt.hardness = 1;

prototypes.stone = new Block;
prototypes.stone.texture = new Image("stone.jpg");
prototypes.stone.hardness = 9;

Таким образом, вместо того, чтобы создавать подклассынаписал бы new DirtBlock или new StoneBlock, вместо этого вы бы написали prototypes.dirt.clone() или prototypes.stone.clone().Никакого подкласса не требуется, но у вас все еще есть возможность создать подкласс, если это необходимо.

Различия с фабричным шаблоном

Что касается того, когда выбирать шаблон прототипа вместо заводского, существует дваЯ могу представить себе ситуации, в которых они различаются:

  1. Вы можете перебирать список прототипов, но вы не можете перебрать все методы на абстрактной фабрике ^.Продолжая приведенный выше код, вы можете создать случайный блок следующим образом:

    prototypes.allValues().objectAtIndex(rand() % prototypes.size()).clone();

    Если бы вы использовали фабричный метод для создания блоков, было бы сложнее получить случайный блок.

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

    Image loadUserImage() { 
        //loads from disk. will be slow
        return new JPEGImage("path/to/user/image.jpg"); 
    }
    

    Если этот метод будет вызываться неоднократно, было бы более эффективно использовать прототип, например, так:

    Image loadUserImage() {
        //copy in memory. will be fast
        return userImagePrototype.clone();
    }
    


^ Это ложь, потому что вы можете перебирать методы в зависимости от того, какой язык вы используете, но перебор массива все еще, вероятно, лучшее решение, потому что он менее сложенчем отражение / самоанализ.

15 голосов
/ 27 ноября 2012

Увеличение эффективности использования прототипа сомнительно для меня. Повышение эффективности не будет, потому что в большинстве языков метод clone сам выполняет вызов new для создания нового экземпляра объекта.

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

...