00 (1158679), страница 14
Текст из файла (страница 14)
Клиенты вызывают операции Component. Если получатель запроса – лист, то он и обрабатывает запрос. Если – составной объект, то он дополнительно рассылает запросы своим частям.
Результаты:
-
упрощается клиент, т. к. он единообразно работает с целым и частями;
-
облегчается добавление новых классов – они являются подклассами Leaf или Composite;
-
трудно ограничить состав видов объектов в составе композиции того или иного вида.
Мост (Bridge)
Классификация: структурный образец.
Назначение: отделить абстракцию от реализации.
Мотивация: наследование жестко привязывает реализацию к абстракции, поэтому лучше иметь иерархию наследования для интерфейсов и отдельно их реализации.
Ситуации применимости:
-
обеспечение независимости абстракции и реализации;
-
необходимо расширять подклассами как интерфейсы, так и их реализации;
-
изменения в реализации не должны влиять на клиента;
-
необходимо разделить большую иерархию наследования на части.
Участники:
-
Abstraction – абстракция, в которой определен интерфейс требуемый клиенту;
-
RefinedAbstraction – уточненная абстракция с расширенным интерфейсом;
-
Implementor – интерфейс для классов-реализаций;
-
ConcreteImplementor – конкретный реализатор.
Отношения:
Абстракция перенаправляет запросы клиента одной из реализаций Implementora.
Результаты:
-
реализация отделяется от интерфейса;
-
чтобы заменить реализацию нет необходимости перекомпилировать абстакцию и ее клиента;
-
система становится более легко модифицируемой.
Фасад (Facade)
Структурный паттерн, идея которого в том, чтобы предоставить унифицированный интерфейс к подсистеме (или пакету) в виде прокси-класса SubsystemProxy (в случае пакета – в виде фасада пакета).
Используется для предоставления простого интерфейса к сложной подсистеме, явного определения точки входа в подсистему, сокращения связей клиентов подсистемы с ее внутренними классами.
Упрощает работу с подсистемой, ослабляет связность, скрывает внутреннее устройство подсистемы.
Proxy (Заместитель)
Классификация: структурный образец.
Назначение: для объекта создается суррогат, контролирующий доступ.
Мотивация: есть «тяжелый» класс, объекты которого разумно создавать по требованию – эта обязанность возлагается на легкие суррогаты.
Ситуации применимости:
-
удаленный заместитель (тяжелый объект невыгодно перемещать с узла на узел, поэтому на другом узле его представляет заместитель);
-
виртуальный заместитель;
-
защищающий заместитель (проверяет права доступа).
Участники:
-
Proxy – заместитель, хранящий ссылку на реальный объект;
-
Class_Client – клиентский класс;
-
Subject –общий интерфейс для класса и его заместителя;
-
RealClass – класс, для которого создается заместитель.
Отношения:
Заместитель получает запрос клиента и переадресует его реальному классу. Детали зависят от вида заместителя.
Результаты (зависят от вида заместителя):
-
удаленный заместитель скрывает тот факт, что реальный объект находится на другом узле (можно экономить сетевой трафик, если создать локальный заместитель удаленного объекта с копиями часто используемых атрибутов);
-
виртуальный заместитель оптимизирует приложение («тяжелые» объекты создаются по требованию, пока в их создании нет необходимости, их представляют «легкие» объекты-заместители);
-
защищающий заместитель обеспечивает нужный режим доступа к объекту.
Цепочка обязанностей (Chain of Responsibility)
Классификация: образец поведения.
Назначение: избежать привязки отправителя запроса к получателю, давая возможность передать запрос через многих (заранее неизвестно скольких) посредников.
Ситуации применимости:
-
есть более одного объекта, способного обработать запрос, настоящий обработчик неизвестен и должен быть найден автоматически (передадим по цепочке, пока кто-нибудь не обработает);
-
адресат запроса не указан, но один из группы;
Участники:
-
Handler – обобщенный обработчик, все специальные обработчики в цепочке являются его подклассами;
-
ConcreteHandler – конкретный обработчик:
-
обрабатывает запрос;
-
знает следующего по цепочке;
-
если может обработать – обрабатывает, иначе передает дальше.
-
Client – отправляет запрос началу цепочки.
Результаты:
-
ослабляется связность (клиент связан лишь с началом цепочки);
-
гибкость в распределении обязанностей;
-
нет гарантий, что запрос будет обработан, может дойти до конца цепочки и пропасть.
Iterator (Итератор)
Классификация: образец поведения.
Назначение: дать последовательный доступ к набору однородных объектов, не раскрывая его внутреннего представления.
Ситуация применимости: есть структура данных, для которой нужно реализовать один или несколько способов обхода – каждый осуществляется отдельным итератором.
Участники:
-
Iterator – общий интерфейс для доступа и обхода структуры данных;
-
ConcreteIterator –
-
конкретный способ обхода;
-
помнит позицию курсора (текущий элемент);
-
Aggregate – интерфейс для создания итератора;
ConcreteAggregate – реализация интерфейса Aggregate.
Результаты:
-
поддерживаются разные способы обхода;
-
упрощается интерфейс Aggregate;
-
есть возможность иметь одновременно несколько активных обходов (столько, сколько объектов-итераторов).
Strategy (Стратегия)
Классификация: образец поведения.
Назначение: Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми.
Мотивация: есть несколько алгоритмов решения одной задачи, которые нежелательно «зашивать» в клиентский класс.
Ситуации применимости:
-
Имеется много родственных классов, отличающихся только поведением.
-
Необходимо иметь несколько разных реализаций одной операции.
-
Нужно скрыть от клиента сложные, специфичные для алгоритма структуры данных.
-
Упрощение кода метода, представляющего собой длинное ветвление или switch.
Участники:
-
Strategy – интерфейс общий для семейства алгоритмов;
-
ConcreteStrategy – конкретная стратегия, реализующая интерфейс;
-
Context – контекст, направляющий запросы клиента стратегиям;
-
Client – клиентский класс.
Результаты:
-
Иерархия классов стратегий определяет семейство алгоритмов или поведений, которые можно повторно использовать.
-
Инкапсуляция алгоритма в отдельный класс позволяет изменять его независимо от контекста.
-
Избавляемся от if и switch (улучшаем читаемость кода).
-
Интерфейс класса Strategy общий для всех подклассов ConcreteStrategy – неважно, сложна или тривиальна их реализация. Поэтому вполне вероятно, что некоторые стратегии не будут пользоваться всей передаваемой им информацией, особенно простые.
Decorator (Декоратор)
Классификация: структурный образец.
Назначение: добавление объекту новых обязанностей в динамике. Альтернатива подклассам.
Мотивация: Например, хотим, чтобы библиотека GUI могла добавлять свойства (рамку) или новое поведение (прокрутку) к любому элементу GUI. Для этого «оборачиваем» элемент GUI в объект-декоратор. Декоратор имеет тот же интерфейс. Он переадресует запросы элементу, который в него «завернут».
Ситуации применимости:
-
для динамического, прозрачного для клиентов добавления обязанностей объектам;
-
для реализации обязанностей, которые могут быть сняты с объекта;
-
когда расширение путем порождения подклассов по каким-то причинам неудобно или невозможно.
Участники:
-
Component – интерфейс для декорируемых объектов;
-
ConcreteComponent – класс декорируемых объектов;
-
Decorator – декоратор, ссылающийся на декорируемый объект и определяющий интерфейс для декораторов, соответствующий интерфейсу Component;
-
ConcreteDecorator – реализует какое-либо дополнительное поведение;
-
Client – клиентский класс.
Результаты:
-
Позволяет гибко добавлять объекту новые обязанности. Обязанности могут быть добавлены или удалены во время выполнения программы. Применение нескольких декораторов обеспечивает сочетание добавляемых обязанностей.
-
Хотя декорированный объект и обычный имеют общий интерфейс, они различны.
-
Получаемая система состоит из множества мелких объектов, которые похожи друг на друга.
Лекция 11. Технология создания программного обеспечения. Rational Unified Process (RUP)
Основные определения:
Технология создания ПО (ТС ПО) – это упорядоченная совокупность взаимосвязанных технологических процессов в рамках ЖЦ ПО.
Технологический процесс – это совокупность взаимосвязанных технологических операций.
Технологическая операция – это основная единица работы, выполняемая определенной ролью, которая:
-
подразумевает четко определенную ответственность роли;
-
дает четко определенный результат (набор рабочих продуктов), базирующийся на определенных исходных данных (другом наборе рабочих продуктов);
-
представляет собой единицу работы с жестко определенными границами, которые устанавливаются при планировании проекта.
Рабочий продукт – информационная или материальная сущность, которая создается, модифицируется или используется в некоторой технологической операции (модель, документ, код, тест и т.п.).
Роль – определение поведения и обязанностей отдельного лица или группы лиц в среде организации-разработчика ПО, осуществляющих деятельность в рамках некоторого технологического процесса и ответственных за определенные рабочие продукты.
Руководство – практическое руководство по выполнению одной или совокупности технологических операций. Руководства включают методические материалы, инструкции, нормативы, стандарты и критерии оценки качества рабочих продуктов.
Инструментальное средство (CASE-средство) – программное средство, обеспечивающее автоматизированную поддержку деятельности, выполняемой в рамках технологических операций.
Основным требованием, предъявляемым к современным ТС ПО, является их соответствие стандартам жизненного цикла (ЖЦ) ПО и оценкой технологической зрелости организаций-разработчиков. Согласно этим нормативам, ТС ПО должна поддерживать полный набор процессов ЖЦ, к которым относятся:
-
управление требованиями;
-
анализ и проектирование ПО;
-
разработка ПО;
-
эксплуатация;
-
сопровождение;
-
документирование;
-
управление конфигурацией и изменениями;
-
тестирование;
-
управление проектом.
Полнота поддержки процессов ЖЦ ПО должна поддерживаться комплексом инструментальных средств (CASE-средств). Также есть ряд других требований:
-
адаптируемость к условиям применения;
-
поддержка поставщика;
-
простота использования;
-
удовлетворительные стоимостные характеристики.
В качестве примера ТС ПО рассмотрим Rational Unified Process (RUP).
RUP в значительной степени соответствует указанным выше требованиям. Ее основными принципами являются:
-
Раннее определение рисков и выработка ответных мер. В начале каждой стадии ЖЦ составляется список рисков (примеры: неосвоенная СП, интеграция с унаследованным кодом, орг. проблемы). По каждому риску из списка составляется перечень ответных мер. RUP учитывает изменчивость рисков – на разных этапах проекта списки рисков разные.
-
Выполнение требований заказчиков. Требования описываются вариантами использования. Варианты использования – это отправная точка создания для модели анализа и проектной модели. Планирование и управление проектом ведется на основе вариантов использования. Варианты использования являются «сырьем» для тестов и пользовательской документации.
-
Концентрация на работающем коде. Прогресс проекта оценивается по тому, какая часть системы готова и работает. Практика – лучший критерий проверки правильности того или иного решения. Все рабочие продукты проекта за исключением работающего кода являются вспомогательными, поэтому не следует слепо их создавать лишь из-за того, что они указаны в руководствах по RUP.
-
Готовность к изменениям с самого начала проекта и управление ими. Система слишком сложна, чтобы с самого начала получить верное и окончательное проектное решение. Изменения позволяют улучшать принятые решения. Итеративный процесс позволяет исправлять дефекты, допущенные на ранних итерациях. Стоимость изменений в ходе проекта увеличивается. Управление изменениями позволяет уложиться в бюджет и сроки.
-
Сборка системы из компонентов. Компонентная архитектура позволяет воспользоваться преимуществами инкапсуляции: повышает модифицируемость системы и возможности повторного использования ее частей. Стоимость разработки системы может быть снижена за счет использования компонентных платформ (J2EE, .NET).
-
Визуальное моделирование. Графические модели более наглядны, удобны чем тексты на естественных и формальных языках. UML – стандартный язык, так что модели понятны большой аудитории (состоящей не только из людей, но и из CASE-средств), по той же причине имеется больше возможностей для повторного использования моделей.
-
Обеспечение качества в течение всего ЖЦ. Используется упреждающее тестирование, лозунг которого: «Тесты раньше программ!» Регрессионное тестирование и первоочередная реализация приоритетных вариантов использования обеспечивают надежность ключевой функциональности системы. Качество создается в течение всего жизненного цикла за счет того, что все рабочие продукты критически оцениваются при рецензировании.
общее представление RUP в двух измерениях («диаграмма с горбами»):
-
горизонтальное измерение представляет время, отражает динамические аспекты процессов и оперирует такими понятиями, как стадии, итерации и контрольные точки;
-
вертикальное измерение отражает статические аспекты процессов и оперирует такими понятиями, как виды деятельности, рабочие продукты, исполнители и дисциплины;
-
высота «горбов» в каждой точке проекта показывает интенсивность работ, выполняемых в рамках того или иного процесса ЖЦ.
Динамический аспект
Согласно технологии RUP, ЖЦ ПО разбивается на отдельные циклы, в каждом из которых создается новое поколение продукта. Каждый цикл, в свою очередь, разбивается на четыре последовательные стадии:
начальная стадия (inception);