Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Паттерны проектирования. Общие понятия.

Поиск

Паттерны проектирования - описание взаимодействия объектов и классов, адаптированных для решения общей задачи проектирования в конкретном контексте. В общем случае паттерн состоит из четырех основных элементов: 1)имя - сославшись на него, мы можем сразу описать проблему проектирования, ее решения и их последствия; 2)задача - описание того, когда следует применять паттерн; 3)решение - описание элементов дизайна, отношений между ними, функций каждого элемента; 4)результаты - это следствия применения паттерна и разного рода компромиссы.

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

1)Название и классификация паттерна. Название паттерна должно четко отражать его назначение.

2)Назначение. Лаконичный ответ на следующие вонросы: каковы функции паттерна, его обоснование и назначение, какую конкретную задачу проектирования можно решить с его помощью.

3)Известен также под именем. Другие распространенные названия паттерна, если таковые имеются.

4)Мотивация. Сценарий, иллюстрирующий задачу проектирования и то, как она решается иной структурой класса или объекта. Благодаря мотивации можно лучше понять последующее, более абстрактное описание паттерна.

5)Применимость. Описание ситуаций, в которых можно применять данный паттерн. Примеры проектирования, которые можно улучшить с его помощью. Распознавание таких ситуаций.

6)Структура. Графическое представление классов в паттерне с использованием нотации, основанной на методике Object Modeling Technique (OMT) [RBP+91].

7)Участники. Классы или объекты, задействованные в данном паттерне проектирования, и их функции.

8)Отношения. Взаимодействие участников для выполнения своих функций.

9)Результаты. Насколько паттерн удовлетворяет поставленным требованиям? Результаты применения, компромиссы, на которые приходится идти. Какие аспекты поведения системы можно независимо изменять, используя данный паттерн?

10)Реализация. Сложности и так называемые подводные камни при реализации паттерна. Советы и рекомендуемые приемы. Есть ли у данного паттерна зависимость от языка программирования?

11)Пример кода. Фрагмент кода, иллюстрирующий вероятную реализацию на языках С++ или Smalltalk.

12)Известные применения. Возможности применения паттерна в реальных системах. Даются, по меньшей мере, два примера из различных областей.

13)Родственные паттерны. Связь других паттернов проектирования с данным. Важные различия. Использование данного паттерна в сочетании с другими.

Виды паттернов проектирования. Порождающие паттерны.

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

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

простое инстанцирование класса. Для порождающих паттернов актуальны две темы. Во-первых, эти паттерны инкапсулируют знания о конкретных классах, которые применяются в системе.

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

компиляции) или динамически (во время выполнения). Иногда допустимо выбирать между тем или иным порождающим паттерном. Например, есть случаи, когда с пользой для дела можно использовать как прототип, так и абстрактную фабрику. В других ситуациях порождающие паттерны дополняют друг друга. Так, применяя строитель, можно использовать другие паттерны для решения вопроса о том, какие компоненты нужно строить, а прототип часто реализуется вместе с одиночкой. Всего существует 5 видов порождающих паттернов: Abstract Factory, Builder, Factory Method, Prototype, Singleton.

Паттерн Abstract Factory.

1)Название и классификация паттерна. Абстрактная фабрика - паттерн, порождающий объекты.

2)Назначение. Предоставляет интерфейс для создания семейств взаимосвязанных или

взаимозависимых объектов, не специфицируя их конкретных классов.

3)Известен также под именем. Kit (инструментарий).

4)Применимость

Используйте паттерн абстрактная фабрика, когда:

□ система не должна зависеть от того, как создаются, компонуются и представляются входящие в нее объекты;

□ входящие в семейство взаимосвязанные объекты должны использоваться вместе и вам необходимо обеспечить выполнение этого ограничения;

□ система должна конфигурироваться одним из семейств составляющих ее объектов;

□ вы хотите предоставить библиотеку объектов, раскрывая только их интерфейсы, но не реализацию.

5)Участники

□ AbstractFactory (WidgetFactory) - абстрактная фабрика: - объявляет интерфейс для операций, создающих абстрактные объекты- продукты;

□ ConcreteFactory(MotifWidgetFactory, PMWidgetFactory) - конкретная фабрика: - реализует операции, создающие конкретные объекты-продукты;

□ AbstractProduct (Window, ScrollBar) - абстрактный продукт: - объявляет интерфейс для типа объекта-продукта;

□ ConcreteProduct(MotifWindow,MotifScrollBar) - конкретный продукт: - определяет объект-продукт, создаваемый соответствующей конкретной фабрикой;

- реализует интерфейс AbstractProduct;

□Client - клиент: - пользуется исключительно интерфейсами, которые объявлены в классах

AbstractFactory и AbstractProduct.

6)Отношения

□Обычно во время выполнения создается единственный экземпляр класса ConcreteFactory. Эта конкретная фабрика создает объекты-продукты, имеющие вполне определенную реализацию. Для создания других видов объектов клиент должен воспользоваться другой конкретной фабрикой;

□ AbstractFactory передоверяет создание объектов-продуктов своему подклассу ConcreteFactory.

7)Результаты

Паттерн абстрактная фабрика обладает следующими плюсами и минусами:

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

известны только конкретной фабрике, в коде клиента они не упоминаются;

□ упрощает замену семейств продуктов. Класс конкретной фабрики появляется в приложении только один раз: при инстанцировании. Это облегчает замену используемой приложением конкретной фабрики. Приложение может изменить конфигурацию продуктов, просто подставив новую конкретную фабрику. Поскольку абстрактная фабрика создает все семейство продуктов,

то и заменяется сразу все семейство.

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

это ограничение;

□ поддержать новый вид продуктов трудно. Расширение абстрактной фабрики для изготовления новых видов продуктов - непростая задача. Интерфейс AbstractFactory фиксирует набор продуктов, которые можно создать. Для поддержки новых продуктов необходимо расширить интерфейс фабрики, то есть изменить класс AbstractFactory и все его подклассы.

8)Реализация

Вот некоторые полезные приемы реализации паттерна абстрактная фабрика:

Реализация

Вот некоторые полезные приемы реализации паттерна абстрактная фабрика:

Реализация

Вот некоторые полезные приемы реализации паттерна абстрактная фабрика:

□фабрики как объекты, существующие в единственном экземпляре. Как правило, приложению нужен только один экземпляр класса ConcreteFactory на каждое семейство продуктов. Поэтому для реализации лучше всего применить паттерн одиночка;

□создание продуктов. Класс AbstractFactory объявляет только интерфейс для создания продуктов. Фактическое их создание - дело подклассов ConcreteProduct. Чаще всего для этой цели определяется фабричный метод для каждого продукта. Если семейств продуктов может быть много, то конкретную фабрику удастся реализовать с помощью паттерна прототип. В этом случае она инициализируется экземпляром-прототипом каждого продукта в семействе и создает новый продукт путем клонирования этого прототипа.

□ определение расширяемых фабрик. Класс AbstractFactory обычно определяет разные операции для каждого вида изготавливаемых продуктов. Виды продуктов кодируются в сигнатуре операции. Для добавления нового вида продуктов нужно изменить интерфейс класса AbstractFactory и всех зависящих от него классов. Более гибкий, но не такой безопасный способ - добавить параметр к

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

9) Родственные паттерны

Классы AbstractFactory часто реализуются фабричными методами, но могут быть реализованы и с помощью паттерна прототип. Конкретная фабрика часто описывается паттерном одиночка.

Паттерн Builder.

1)Название и классификация паттерна

Строитель - паттерн, порождающий объекты.

2) Назначение

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

3) Применимость

Используйте паттерн строитель, когда:

□ алгоритм создания сложного объекта не должен зависеть от того, из каких частей состоит объект и как они стыкуются между собой;

□процесс конструирования должен обеспечивать различные представления конструируемого объекта.

4) Участники

□ Builder (TextConverter) - строитель:

- задает абстрактный интерфейс для создания частей объекта Product;

□ ConcreteBuiMer (ASCIIConverter, TeXConverter, TextWidgetConverter) -

конкретный строитель:

- конструирует и собирает вместе части продукта посредством реализации

интерфейса Builder;

- определяет создаваемое представление и следит за ним;

- предоставляет интерфейс для доступа к продукту (например, GetASCIIText,

GetTextWidget);

□ Director (RTFReader) - распорядитель:

- конструирует объект, пользуясь интерфейсом Buiider;

□ Product (ASCIIText, TeXText, TextWidget) - продукт:

- представляет сложный конструируемый объект. ConcreteBuilder

строит внутреннее представление продукта и определяет процесс его сборки;

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

5) Отношения

□клиент создает объект-распорядитель Director и конфигурирует его нужным объектом-строителем Builder;

□ распорядитель уведомляет строителя о том, что нужно построить очередную часть продукта;

□ строитель обрабатывает запросы распорядителя и добавляет новые части к продукту;

□ клиент забирает продукт у строителя.

6) Результаты

Плюсы и минусы паттерна строитель и его применения:

□ позволяет изменять внутреннее представление продукта. Объект Builder

предоставляет распорядителю абстрактный интерфейс для конструирования продукта, за которым он может скрыть представление и внутреннюю структуру продукта, а также процесс его сборки. Поскольку продукт конструируется через абстрактный интерфейс, то для изменения внутреннего представления достаточно всего лишь определить новый вид строителя;

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

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

7) Реализация

Обычно существует абстрактный класс Builder, в котором определены операции для каждого компонента, который распорядитель может «попросить» создать. По умолчанию эти операции ничего не делают. Но в классе конкретного строителя ConcreteBuilder они замещены для тех компонентов, в создании которых он принимает участие.

8) Родственные паттерны

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

Паттерн компоновщик - это то, что часто создает строитель.

Паттерн Factory Method.

1)Название и классификация паттерна

Фабричный метод - паттерн, порождающий классы.

2)Назначение

Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанцировать. Фабричный метод позволяет классу делегировать инстанцирование подклассам.

3) Известен также под именем

Virtual Constructor (виртуальный конструктор).

4) Применимость

Используйте паттерн фабричный метод, когда:

□ классу заранее неизвестно, объекты каких классов ему нужно создавать;

□ класс спроектирован так, чтобы объекты, которые он создает,специфицировались подклассами;

□ класс делегирует свои обязанности одному из нескольких вспомогательных подклассов, и вы планируете локализовать знание о том, какой класс принимает эти обязанности на себя.

5)Участники

□ Product (Document) - продукт:

- определяет интерфейс объектов, создаваемых фабричным методом;

□ ConcreteProduct (MyDocument) - конкретный продукт:

- реализует интерфейс Product;

□Creator(Application) - создатель:

- объявляет фабричный метод, возвращающий объект типа Product.

Creator может также определять реализацию но умолчанию фабричного метода, который возвращает объект ConcreteProduct;

- может вызывать фабричный метод для создания объекта Product.

□ConcreteCreator (MyApplication) - конкретный создатель:

- замещает фабричный метод, возвращающий объект ConcreteProduct.

6)Отношения

Создатель «полагается» на свои подклассы в определении фабричного метода, который будет возвращать экземпляр подходящего конкретного продукта.

7)Результаты

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

одного объекта ConcreteProduct. Порождение подклассов оправдано, если клиенту так или иначе приходится создавать подклассы Creator, в противном случае клиенту придется иметь дело с дополнительным уровнем подклассов.

8) Реализация

Рассмотрим следующие вопросы, возникающие при использовании паттерна

фабричный метод:

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

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

9) Родственные паттерны

Абстрактная фабрика часто реализуется с помощью фабричных методов. Паттерн фабричные методы часто вызывается внутри шаблонных методов.

Паттерн Prototype.

1)Название и классификация паттерна

Прототип - паттерн, порождающий объекты.

2)Назначение

Задает виды создаваемых объектов с помощью экземпляра-прототипа и создает новые объекты путем копирования этого прототипа.

3) Применимость

Используйте паттерн прототип, когда система не должна зависеть от того, как в ней создаются, компонуются и представляются продукты:

□ инстанцируемые классы определяются во время выполнения, например с помощью динамической загрузки;

□ для того чтобы избежать построения иерархий классов или фабрик, параллельных иерархии классов продуктов;

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

4) Участники

□ Prototype (Graphic) - прототип:

- объявляет интерфейс для клонирования самого себя;

□ConcretePrototype (Staff- нотный стан, WholeNote- целая нота, HalfNote - половинная нота) - конкретный прототип:

- реализует операцию клонирования себя;

□ Client (GraphicTool) - клиент:

- создает новый объект, обращаясь к прототипу с запросом клонировать себя.

5)Отношения

Клиент обращается к прототипу, чтобы тот создал свою копию.

6) Результаты

У прототипа те же самые результаты, что у абстрактной фабрики и строителя: он скрывает от клиента конкретные классы продуктов, уменьшая тем самым число известных клиенту имен. Кроме того, все эти паттерны позволяют клиентам работать со специфичными для приложения классами без модификаций. Основной недостаток паттерна прототип заключается в том, что каждый подкласс класса Prototype должен реализовывать операцию Clone, a это далеко не всегда просто.

7) Реализация

Рассмотрим основные вопросы, возникающие при реализации прототипов:

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

□ реализация операции Clone. Самая трудная часть паттерна прототип - правильная реализация операции Clone. Особенно сложно это в случае, когда в структуре объекта есть круговые ссылки.

□инициализация клопов. Хотя некоторым клиентам вполне достаточно клона как такового, другим нужно инициализировать его внутреннее состояние полностью или частично. Обычно передать начальные значения операции Clone невозможно, поскольку их число различно для разных классов прототипов. Для некоторых прототипов нужно много параметров инициализации, другие вообще ничего не требуют. Передача Clone параметров мешает построению единообразного интерфейса клонирования.

8) Родственные паттерны

В некоторых отношениях прототип и абстрактная фабрика являются конкурентами. Но их используют и совместно. Абстрактная фабрика может хранить набор прототипов, которые клонируются и возвращают изготовленные объекты.



Поделиться:


Последнее изменение этой страницы: 2016-08-14; просмотров: 910; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.147.62.5 (0.009 с.)