Лекция 10 (проектирование связей между классами).

реклама
Моделирование и проектирование
программного обеспечения
Лекция xx.
Проектирование связей между
классами
Проектирование связей между
классами
Определение ассоциаций между
классами
• Все ассоциации между классами должны
тщательно продуманы.
• Многие ассоциации перейдут в проектную
модель непосредственно из модели анализа,
• Большой набор ассоциаций вводится в связи
– ограничений реализации или
– желания повторно использовать код.
• Новые ассоциации модели проектирования
необходимо проверять наиболее внимательно:
– некоторая степень связанности хороша и необходима.
• Допускается высокая связанность в рамках
подсистемы, поскольку это указывает на
сцепленность (высокую связность) компонента.
• Нарушают архитектуру только многочисленные
связи между подсистемами.
– Необходимо активно стремиться к сокращению
подобной связанности.
Степень связанности разных
отношений классов
• Все виды связанности можно упорядочить по
степени убывания следующим образом:
1.
2.
3.
4.
Наследование (наиболее строгая связанность).
Композиция
Агрегирование
Ассоциация
Наследование
• При проектировании наследование играет намного
более важную роль, чем при анализе.
• В анализе наследование использовалось, только в
том случае, если между классами анализа имело место
четкое и явно выраженное отношение «является» («is
a»).
• Однако при проектировании наследование может
применяться в тактических целях для повторного
использования кода.
• Это совсем другой метод, т.к. наследование
фактически используется для упрощения реализации
дочернего класса, а не для описания бизнесотношения между родителем и потомком.
Сравнение агрегации и
наследования
• Наследование – очень мощный метод.
– Оно является ключевым механизмом формирования
полиморфизма в строго типизированных языках
программирования, таких как Java, C# и C++.
• Однако неопытные ОО проектировщики и
программисты часто используют его
неправильно.
• Необходимо понимать, что наследование имеет
некоторые нежелательные характеристики:
– Наследование – самая строгая форма связанности
классов.
– Это самая строгая из возможных форма связанности
двух или более классов.
• В иерархии классов будет плохая
инкапсуляция.
– связано с тем, что изменения базового класса
передаются вниз по иерархии и приводят к
изменениям всех подклассов.
• Такое явление называется проблемой
«хрупкости базового класса», когда изменения
базового класса имеют огромное влияние на
другие классы системы.
• Во всех широко используемых ОО языках
программирования отношения наследования
постоянны во время выполнения.
– Во время выполнения, можно изменять иерархии
агрегации и композиции (создавая и уничтожая
объекты), но иерархии наследования остаются
неизменными.
• Это делает наследование самым жестким
типом отношений между классами.
Пример
• Задача моделирования сотрудников организации: есть
сотрудник, которые могут иметь разные должности.
– Решение выполненное неопытным разработчиком.
• Имеется смысловая (семантическая) ошибка.
– служащий (Employee) это
• именно сама должность (Job)
• или указание на то, что служащий занимает некоторую должность?
• При использовании агрегации получаем правильный смысл:
– у служащего (Employee) есть должность (Job).
• При такой более гибкой модели у служащих при необходимости
может быть несколько должностей.
• Подклассы всегда должны представлять «особую разновидность
чего-либо», а не «выполняемую роль».
Сравнение наследования и реализации
интерфейса
• При наследовании класс получает:
– интерфейс – открытые операции базовых классов;
– реализацию – атрибуты, отношения, защищенные и
закрытые операции базовых классов.
• При реализации интерфейса класс получает:
– интерфейс – набор открытых операций, атрибутов и
отношений, не имеющих реализации.
• У наследования и реализации интерфейса есть
что-то общее, поскольку оба этих механизма
обеспечивают возможность описания контракта,
который должен быть реализован подклассами.
– Однако семантика и применение этих двух методов
совершенно разные.
Рекомендация
• В начале использования ОО подхода наследование
часто считали основным механизмом многократного
использования.
• Однако разработчики выявили появление
неприемлемых ограничений, накладываемых
наследованием.
• В связи с этим в настоящее время широкое применение
наследования не рекомендуется.
• Наследование должно использоваться только
тогда, когда речь идет о наследовании от
суперкласса некоторых деталей реализации
(операций, атрибутов, отношений).
– Это одна из разновидностей многократного использования.
Реализация интерфейса
• Реализация интерфейса полезна везде, где
необходимо определить контракт, но без
наследования деталей реализации.
• Реализация интерфейса фактически не
обеспечивает повторного использования кода, но
– предоставляет точный способ описания контрактов и
– гарантирует их выполнение классами реализации.
• Т.к. в реализации интерфейса ничего не
наследуется, это более гибкий и надежный
способ проектирования, чем наследование.
Уточнение отношений,
выявленных на этапе анализе
Отношения этапа проектирования
• При переходе к проектированию необходимо уточнить
отношения между классами анализа и превратить их в
отношения между проектными классами.
• Многие из выявленных при анализе отношений не
могут быть реализованы непосредственно, как они
описаны, их надо специально подготовить.
– Например, ни один из широко распространенных ОО
языков программирования не поддерживает
двунаправленные ассоциации, классы-ассоциации или
ассоциации «многие-ко-многим».
• При создании проектной модели, необходимо
определить, как такие ассоциации должны быть
реализованы.
• Уточнение ассоциаций анализа до ассоциаций этапа
проектирования включает несколько процедур:
– уточнение ассоциаций до отношений агрегации или
композиции в соответствующих случаях;
– реализацию ассоциаций «один-ко-многим»;
– реализацию ассоциаций «многие-к-одному»;
– реализацию ассоциаций «многие-ко-многим»;
– реализацию двунаправленных ассоциаций;
– реализацию классов-ассоциаций.
• Все ассоциации уровня проектирования должны обладать:
– возможностью навигации;
– кратностью на обоих концах.
• У всех ассоциаций уровня проектирования должно быть
указано имя ассоциации или имя роли, по крайней мере,
на целевом конце.
Агрегация и композиция
• При проектировании отношение ассоциация
можно уточнить до агрегации или более
строгой формы агрегации – композиции
(композитной агрегации), если ассоциация
имеет соответствующую семантику.
– Агрегация – это свободный тип отношения между
объектами – как между компьютером и его
периферийным оборудованием.
– Композиция – это очень строгий тип отношения
между объектами – как между деревом и его
листьями.
Пример агрегации
• Пример агрегации: компьютер очень слабо
взаимосвязан со своим периферийным
оборудованием.
– Периферийные устройства могут появляться и
исчезать, могут совместно использоваться с другими
компьютерами.
– Они не «принадлежат» конкретному компьютеру.
Пример композиции
• Пример композиции: дерево тесно
взаимосвязано со своими листьями.
– Листья принадлежат только одному дереву, ими
нельзя поделиться с другими деревьями, и когда
дерево умирает, листья умирают вместе с ним.
Семантика агрегации
• Агрегация – это тип отношения «целое-часть», в
котором агрегат образуется многими частями.
• В отношении «целое-часть» один объект (целое)
использует сервисы другого объекта (части).
• По существу, целое является доминантной и
управляющей стороной отношения, тогда как
часть просто обслуживает запросы целого и,
следовательно, играет более пассивную роль.
– Если навигацию можно осуществлять только от целого
к части, последняя даже не знает, что является частью
целого.
Пример агрегации
• Из данного примера видно, что:
– компьютер (класс Computer) может быть присоединен к 0
или более принтерам (класс Printer);
– в любой момент времени принтер соединен с 0 или 1
компьютером;
– в ходе времени конкретный принтер может
использоваться многими компьютерами;
– принтер может существовать, даже если не подключен
ни к одному компьютеру;
– принтер фактически не зависит от компьютера.
Семантика агрегации
• агрегат может существовать как независимо
от частей, так и вместе с ними;
• части могут существовать независимо от
агрегата;
• агрегат является в некотором смысле
неполным в случае отсутствия некоторых
частей;
• части могут принадлежать одновременно
нескольким агрегатам.
Агрегация транзитивна
• Транзитивность означает, что если C является
частью B, и B является частью A, тогда C также
является частью A.
Агрегация асимметрична
• Это означает, что объект никогда – ни прямо, ни
косвенно – не может быть частью самого себя.
• Это ограничивает способы использования агрегации в
моделях.
• В приведенном ниже примере показано, что объекты
Product могут состоять из других объектов Product.
– Здесь нет ошибки, т.к. это разные объекты, и ограничение
асимметрии не нарушено.
• Иногда может понадобиться смоделировать ситуацию, когда между
объектами d и a существует связь, как показано на рисунке.
• Такое может случиться, если объекту d необходимо осуществить
обратный вызов и использовать некоторые сервисы объектаагрегата a.
• Рефлексивная агрегация с классом Product не подходит, потому что
согласно ограничению асимметрии для агрегации объект a не
может быть частью самого себя ни прямо, ни косвенно.
• Поэтому для обработки связи между
объектами d и a необходимо использовать
рефлексивную неуточненную ассоциацию (это
уже не агрегация) класса Product с самим
собой, как показано ниже.
Ассоциация симметрична
• Объект может быть ассоциирован с самим собой.
• На приведенной схеме показан другой типичный пример
агрегации.
• Домашний компьютер (целое) может быть смоделирован как набор
частей.
• Эти части довольно слабо взаимосвязаны с целым.
• Их можно переносить с компьютера на компьютер или
использовать совместно с другими компьютерами, поэтому в этой
модели применима семантика агрегации.
• Согласно этой модели домашний компьютер можно рассматривать как
совокупность следующих частей:
–
–
–
–
–
Mouse (мышь),
Keyboard (клавиатура),
CPU (центральный процессор),
Monitor (монитор) и
два объекта Speaker (колонка).
• CPU, в свою очередь, может быть смоделирован как совокупность
различных аппаратных компонентов, таких как
– RAM (ОЗУ),
– HardDrive (жесткий диск)
– и т. д.
Семантика композиции
• Композиция это более строгая форма агрегации.
• Она имеет сходную (но более строгую)
семантику.
• Как и агрегация, это отношение «целое-часть»,
являющееся как транзитивным, так и
асимметричным.
• Ключевое различие между агрегацией и
композицией в том, что в композиции у частей
нет независимой жизни вне целого.
• В композиции каждая часть принадлежит
максимум одному и только одному целому,
– тогда как при агрегации часть может совместно
использоваться несколькими целыми.
Пример композиции
• В примере объекты Button (кнопка) не могут существовать
независимо от владеющего ими объекта Mouse.
• Если уничтожается объект Mouse, уничтожаются и
принадлежащие ему объекты Button, потому что они
являются его неотъемлемой частью.
• Каждый объект Button может принадлежать только одному
объекту Mouse.
• Так же и листья на деревьях – жизнь листа определяется
жизнью дерева, и лист может принадлежать только одному
дереву.
Семантика композиции
• одновременно части могут принадлежать только
одному композиту – совместное владение
частями невозможно;
• композит обладает исключительной
ответственностью за все свои части;
– он отвечает за их создание и уничтожение;
• композит может высвобождать части, передавая
ответственность за них другому объекту;
• в случае уничтожения композита он должен или
уничтожить все свои части, или передать
ответственность за них другому объекту.
• Композитный объект обладает полной
ответственностью за жизненный цикл и
управление своими частями.
– при создании он часто создает и свои части;
– при уничтожении он должен
• уничтожить все свои части или
• организовать их передачу другому композиту.
• Для рефлексивной агрегации могут быть
иерархии, и сети рефлексивной агрегации,
• Для рефлексивной композиции возможны
только иерархии.
Композиция и атрибуты
• Семантика композиции очень похожа на
семантику атрибутов.
– жизненный цикл в обоих случаях контролируется
владельцами.
– части, и атрибуты не могут независимо
существовать вне своих владельцев.
• Фактически, атрибуты – это точный эквивалент
отношения композиции между классом
композита и классом атрибута.
Когда использовать композицию и
атрибуты
1. Типом атрибута может быть простой тип данных.
– В некоторых ОО языках программирования (например, C++ и
Java), есть простые типы (например, int и double), которые не
являются классами.
– Простые типы можно моделировать как классы (с
использованием стереотипа «primitive»), но это сильно
загромождает модель.
– Простые типы всегда должны моделироваться как
атрибуты.
2. Существуют определенные, широко используемые
вспомогательные классы, такие как Time, Date и String.
– Если каждый раз моделировать эти классы с помощью
отношения композиции, то очень скоро модели становятся
абсолютно непонятными.
– Намного лучше моделировать такие классы как
атрибуты.
Порядок уточнения отношения уровня
анализа
• При анализе использовались простые
ассоциации без какого-либо подробного
рассмотрения семантики отношения (или того,
каким образом отношение должно быть
реализовано).
• Однако при проектировании необходимо всегда
пытаться достичь максимальной конкретизации
и уточнить ассоциации до одного из отношений
агрегации везде, где это возможно.
• Фактически ассоциация должна использоваться
в проектировании, только в том случае, если
схема агрегации образуется цикл.
• Такая ситуация встречается редко, поэтому
большинство аналитических ассоциаций
превращаются или в агрегацию, или в
композицию.
• Ассоциации этапа анализа должны быть
уточнены до одного из отношений агрегации
везде, где это возможно.
• После того как принято решение о применении
агрегации или композиции, необходимо
действовать следующим образом:
1. добавить в ассоциации кратности и имена ролей,
если они отсутствуют;
2. выбрать, какой конец ассоциации является целым, а
какой – частью;
• посмотреть на кратность связи со стороны целого; если это
«0..1» или 1, вероятно, можно использовать композицию;
• в противном случае должна использоваться агрегация;
3. добавить возможность навигации от целого к части –
• ассоциации уровня проектирования должны быть
однонаправленными.
Ассоциации «один-к-одному»
• Практически всегда ассоциация «один-к-одному»
превращается в композицию.
• По сути, ассоциация «один-к-одному» подразумевает
настолько строгое отношение между двумя классами, что
стоит рассмотреть возможность их объединения в один
класс без нарушения правил проектирования.
• Если классы нельзя объединить, отношение «один-кодному» уточняется до композиции, как показано на рис.
• Можно рассмотреть возможность превращения PartyIdentifier (идентификатор команды) в атрибут класса
Party (команда)
– если PartyIdentifier не является особо важным классом.
• Упрощает диаграмму, но имеет и недостаток:
– нельзя показать атрибуты или операции, принадлежащие
классу PartyIdentifier.
Ассоциации «многие-к-одному»
• Если со стороны целого кратность равна «много»,
то
– композиция становится невозможной, потому что
часть используется совместно многими целыми.
– возможна агрегация.
• Необходимо выполнить проверку на наличие
циклов в схеме агрегации.
• Если циклов в ассоциации «многие-к-одному» не
обнаружены, то ассоциацию «многие-к-одному»
этапа анализа можно уточнять до агрегации.
• Ассоциации «многие-к-одному» подразумевают
агрегацию, если в схеме агрегации нет цикла.
Ассоциации «многие-к-одному»
• Если циклов в ассоциации «многие-к-одному» не
обнаружены, то ассоциацию «многие-к-одному»
этапа анализа можно уточнять до агрегации, как
показано на рис.
– один объект Currency (валюта) совместно
используется многими объектами Money (деньги).
– правильно отражает отношение между деньгами и
валютой: деньги – это сумма в некоторой валюте.
Ассоциации «один-ко-многим»
• В ассоциации «один-ко-многим» со стороны
«части» имеется коллекция объектов.
• Для реализации такого отношения,
необходимо использовать:
– поддержку коллекций, предоставляемую языком
реализации;
– или классы-коллекции.
• Большинство ОО языков программирования
имеют минимальную встроенную поддержку
коллекций объектов.
• В основном, большинство языков
программирования предлагают только массивы:
– Преимуществом встроенных массивов является их
высокая производительность.
– Их недостаток малая гибкостью в сравнении с
другими типами коллекций.
• Классы-коллекции обычно обладают намного
большей мощью и гибкостью, чем массивы.
• Они предлагают разнообразные семантики, в
которых массив является лишь одним из
возможных вариантов.
Коллекции
• «Класс-коллекция» – это класс, экземпляры
которого предназначены для управления
наборами других объектов.
• В большинстве языков программирования
есть стандартные библиотеки классовколлекций (и других утилит).
• Одним из ключей к отличному ОО
проектированию и реализации является
совершенное владение «классамиколлекций».
Операции классов-коллекций
• У всех таких классов есть операции для:
1. добавления объектов в коллекцию;
2. удаления объектов из коллекции;
3. извлечения ссылки на объект, находящийся
в коллекции;
4. обход коллекции, т. е. проход по коллекции
от первого объекта до последнего.
• Существует много типов коллекций, поразному обрабатывающих коллекции
объектов.
• Важным аспектом ОО проектирования и
реализации является правильный выбор типа
коллекции.
Пример использования коллекции
• На рис. показана ассоциация один-ко-многим уровня анализа,
реализованная с помощью класса-коллекции Vector (класс
стандартной библиотеки Java java.util).
• Как правило, между целым (классом Order (заказ)) и классом Vector
устанавливается отношение композиции, поскольку Vector обычно
является всего лишь частью реализации целого и не может
существовать вне него.
• Однако между классом Vector и его частями (OrderLine (строка
заказа)) может существовать отношение агрегации или композиции.
• Если целое несет ответственность за жизненный цикл частей, как в
данном примере, можно использовать композицию.
• В противном случае должна использоваться агрегация.
• С точки зрения моделирования с использованием
коллекций существуют следующие основные
способы:
1. Явное моделирование «класса-коллекции».
2. Задание конкретного «класса-коллекций» для
реализации ассоциации «один-ко-многим».
3. Указание использования коллекций, но без
указания конкретного класса реализации.
4. Уточнение отношения «один-ко-многим» до
«классов-коллекций» не выполняется – решение
этой задачи передается программистам.
1. Явное моделирование класса-коллекции
• Его преимущество в чрезвычайной детализации, однако
есть и большой недостаток – «загроможденность»
проектной модели.
• Если ассоциация «один-ко-многим» заменяется «классомколлекции», модель быстро становится очень раздутой.
• Выбор класса-коллекции обычно является тактическим
решением реализации, и право это сделать можно
передать программистам.
• Рекомендуется заменять ассоциации «один-ко-многим»
конкретными «классами-коллекций», только если выбор
коллекции является стратегически важным.
2. Задание конкретного «класса-коллекций» для
реализации ассоциации «один-ко-многим»
• Многие инструменты моделирования, генерирующие
код, позволяют назначать конкретный «классколлекции» для каждой ассоциации «один-комногим».
• Обычно это осуществляется путем добавления в
ассоциацию помеченных значений, определяющих
свойства генерации кода для данного отношения.
• Пример показан на схеме: на соответствующем конце
отношения указано свойство {Vector}.
– используется только именная часть помеченного значения
– часть «значение» в данном случае является излишней.
3. Указание использования коллекций, но без
указания конкретного класса реализации
• Используемый тип коллекции – часто тактическое, а не
стратегическое решение, которое может быть принято
программистами во время реализации.
• Этот вариант хорош тем, что сохраняется лаконичность
модели, и программистам могут быть предоставлены
подсказки по поводу того, какой «класс-коллекции»
должен использоваться.
• Однако такой подход обычно исключает
автоматическую генерацию кода.
UML обозначения для коллекций
• UML предоставляет стандартные свойства, которые могут применяться
к кратностям для обозначения требуемой семантики коллекции.
Свойство
Семантика
{ordered}
Существует строгий порядок расположения элементов коллекции.
{unordered}
Элементы в коллекции располагаются в произвольном порядке.
{unique}
Все элементы коллекции уникальны – один и тот же объект
появляется в коллекции максимум один раз.
{nonunique}
В коллекции допускается дублирование элементов.
• Упорядоченность - определяет, как располагаются элементы в
коллекции: в строгом порядке относительно друг друга или нет.
• Уникальность - определяет единичность каждого объекта коллекции.
• Для отношения один-ко-многим по умолчанию применяется семантика
{unordered, unique} ({неупорядоченный, уникальный}).
• Сочетания свойств упорядочения и уникальности
создают набор коллекций:
Свойство
Коллекция OCL
{unordered, nonunique}
Bag (мультимножество)
{unordered, unique}
Set (множество)
{ordered, unique}
OrderedSet (упорядоченное множество)
{ordered, nonunique}
Sequence (последовательность)
Конкретизация отношений
• Некоторые типы отношений являются
исключительно элементами анализа и не
поддерживаются напрямую ни одним из широко
используемых ОО языков программирования.
• Процесс реализации таких отношений уровня
анализа называют конкретизацией (reification)
(т. е. превращение в нечто конкретное).
• Конкретизации подвергаются следующие
отношения уровня анализа:
– ассоциации «многие-ко-многим»;
– двунаправленные ассоциации;
– «классы-ассоциации».
Ассоциации «многие-ко-многим»
• Ни один из широко используемых ОО языков
программирования не поддерживает напрямую
ассоциации «многие-ко-многим».
• В связи с этим такие ассоциации необходимо
конкретизировать в обычные классы, отношения
агрегации, композиции и зависимости.
• При анализе такие вопросы, как владение и
навигация, могли бы оставаться неясными, но в
проектировании такая неопределенность
невозможна.
• Это тот случай, когда сначала надо решить, какая
из сторон ассоциации «многие-ко-многим»
является целым, а затем применять
соответственно агрегацию или композицию.
Пример ассоциации «многие-ко-многим»
• В данном примере отношение allocation
(распределение) было конкретизировано в класс
Allocation.
• Это превращает ассоциацию «многие-комногим» в два отношения агрегации.
• Исходя из требований, предъявляемых к системе,
было принято решение, что Resource (ресурс) –
это целое.
• Система главным образом занимается
управлением потоками работ,
ассоциированными с Resource, т. е. является
«ресурсо-центричной».
• Однако если бы система была «задачецентричной», целым был бы сделан объект Task
(задача), что изменило бы направление
отношений, представленных на рисунке.
• Также было решено возложить ответственность
за жизненный цикл объектов Allocation на
Resource, и поэтому используется отношение
композиции.
• Если система пытается представить обе точки
зрения, ее можно было бы назвать
ориентированной на распределение ресурсов.
• Тогда был бы введен новый объект (возможно,
AllocationManager (менеджер распределения)),
обслуживающий список объектов Allocation,
каждый объект которого указывает как на объект
Resource, так и на объект Task.
Двунаправленные ассоциации
• Часто необходимо смоделировать обстоятельства, в
которых
– объект а класса А использует сервисы объекта b класса В, и
– объекту b необходимо делать обратный вызов и использовать
сервисы объекта а.
• Например: управление GUI Window с одним или более
объектами Button, где
– каждому объекту Button надо выполнять обратный вызов и
– использовать сервисы Window, которому они принадлежат.
Конкретизация двунаправленной ассоциации
• При анализе все просто – такая ситуация моделируется
как единственная двунаправленная ассоциация.
• Однако ни один из широко используемых ОО языков
программирования реально не поддерживает
двунаправленные ассоциации.
• Поэтому при проектировании такая ассоциация
должна быть конкретизирована в две
однонаправленные ассоциации или зависимости, как
показано на рис.
• При моделировании обратных вызовов
необходимо помнить об асимметрии агрегации и
композиции – объект никогда – ни прямо, ни
косвенно – не может быть частью самого себя.
• Это значит, что если класс А имеет отношение
агрегации или композиции с классом В, обратный
вызов от В к А должен быть смоделирован как не
конкретизированная ассоциация.
• Если бы между B и A было применено отношение агрегации, объект b
был бы частью (через композицию или агрегацию) объекта а, и
объект а был бы частью (через агрегацию) объекта b.
• Такое замкнутое владение, конечно же, нарушает асимметричность
агрегации.
• Двунаправленные ассоциации также имеют место тогда, когда целое
передает ссылку на себя в качестве параметра одной из операций
части или когда часть в одной из своих операций создает экземпляр
целого.
• В этих случаях необходимо использовать отношение зависимости от
части к целому, а не ассоциацию.
• Если бы между B и A было применено
отношение агрегации,
– объект b был бы частью (через композицию или
агрегацию) объекта а, и
– объект а был бы частью (через агрегацию)
объекта b.
• Такое замкнутое владение, нарушает
асимметричность агрегации.
• Двунаправленные ассоциации также имеют
место тогда, когда целое передает ссылку на
себя в качестве параметра одной из операций
части или когда часть в одной из своих
операций создает экземпляр целого.
• В этих случаях необходимо использовать
отношение зависимости от части к целому, а
не ассоциацию.
«Классы-ассоциации»
• «Классы-ассоциации» – это объекты которые
используются только на этапе анализа; они напрямую
не поддерживаются ни одним из широко
используемых ОО языков программирования.
• Таким образом, они не имеют прямого аналога на
этапе проектирования и должны быть удалены из
проектной модели.
Конкретизация «классов-ассоциаций»
• «Класс-ассоциация» конкретизируется в
обычный класс, а для отражения его
семантики используется сочетание
ассоциации, агрегации, композиции или даже
зависимости.
• Это может потребовать наложения
ограничений на модель.
• Принимается решение, какая из сторон
ассоциации является целым, и соответственно
этому используется композиция, агрегация и
возможность навигации.
Пример класса-ассоциации
• При конкретизации класса-ассоциации теряется его
семантика, которая гласит, что объекты на каждом конце
класса-ассоциации должны формировать уникальную пару.
• Однако, добавив примечание, содержащее
соответствующее ограничение, эту семантику можно
задать.
Шаблоны проектирования
Шаблоны проектирования
• В проектировании ПО часто встречаются
проблемы, которые уже решались ранее в
других проектах.
• В связи с тем, что контексты, в которых данная
проблема решалась, могут различаются
– (другой тип приложения, другая платформа или
другой язык программирования),
– все обычно заканчивается повторением
проектирования и реализации данного решения,
– тем самым возникает ситуация «повторного
изобретения колеса».
• В этом случае разработчикам могут помочь,
программные шаблоны, включая
– архитектурные шаблоны и
– шаблоны проектирования.
• Они позволяют избежать ненужного
повторного проектирования и реализации.
• Понятие шаблона (pattern) впервые было предложено
Christopher Alexander для разработки архитектуры
зданий и описаны в его книге
– «The Timeless Way of Building» (Alexander 1979).
• «Любой паттерн описывает задачу, которая снова и
снова возникает в нашей работе, а также принцип ее
решения, причем таким образом, что это решение
можно потом использовать миллион раз, ничего не
изобретая заново» (Александр Кристофер, архитектор).
• Такое определение верно и в отношении паттернов
объектно-ориентированного проектирования.
Понятие паттерна (шаблона)
• При ООП решения описываются в терминах объектов и
интерфейсов, а не стен и дверей, но в обоих случаях смысл
паттерна - предложить решение определенной задачи в
конкретном контексте.
• Под паттернами ОО проектирования понимается
описание взаимодействия объектов и классов,
адаптированных для решения общей задачи
проектирования в конкретном контексте.
• В области ПО использование шаблонов проектирования
было предложено и развито Gamma, Helms, Johnson и
Vlissides в их книге «Design Patterns (1995)», в которой они
описали 23 шаблона проектирования.
– Э. Гамма, Р. Хелм, Р. Джонсон, Д. Влиссидес «Приемы объектноориентированного проектирования (Паттерны
проектирования)», «ДМК Пресс», СПб, 2010, 368 с.
Типы шаблонов
• Шаблоны проектирования (design patterns)
– Шаблон проектирования это небольшая взаимодействующих
объектов.
• Архитектурные шаблоны (architectural patterns).
– Архитектурные шаблоны это шаблоны описывающие
взаимодействие более крупных элементов, чем шаблоны
проектирования.
– Они предназначенные для определения структуры больших
подсистем программной системы.
• Шаблоны анализа (analysis patterns).
– Fowler (2002) обнаружил сходства в ходе анализа приложений,
разрабатываемых для разных предметных областей.
– Он описал часто повторяющиеся шаблоны найденные в ОО
анализе с помощью статических моделей, представленных в
виде диаграмм классов.
• Идиомы (idioms).
Шаблоны
• Шаблоны позволяют основываться на
коллективном опыте квалифицированных
инженеров по проектированию ПО (ТРПО).
• Они фиксируют существующий, хорошозарекомендовавший себя опыт разработки ПО и
помогает содействовать хорошим методам
проектирования.
• Каждый шаблон имеет дело с конкретной,
многократно встречающейся проблемой в
области проектирования и реализации ПО.
• Шаблоны могут использоваться для создания
архитектур ПО с конкретными свойствами.
Каталог паттернов проектирования
1. Abstract Factory (абстрактная фабрика)
– Предоставляет интерфейс для создания семейств, связанных между собой, или
независимых объектов, конкретные классы которых неизвестны.
2. Adapter (адаптер)
– Преобразует интерфейс класса в некоторый другой интерфейс, ожидаемый
клиентами.
– Обеспечивает совместную работу классов, которая была бы невозможна без
данного паттерна из-за несовместимости интерфейсов.
3. Bridge (мост)
– Отделяет абстракцию от реализации, благодаря чему появляется возможность
независимо изменять то и другое.
4. Builder (строитель)
– Отделяет конструирование сложного объекта от его представления, позволяя
использовать один и тот же процесс конструирования для создания различных
представлений.
5. Chain of Responsibility (цепочка обязанностей)
– Можно избежать жесткой зависимости отправителя запроса от его получателя,
при этом запросом начинает обрабатываться один из нескольких объектов.
– Объекты-получатели связываются в цепочку, и запрос передается по цепочке, пока
какой-то объект его не обработает.
Каталог паттернов проектирования
6. Command (команда)
– Инкапсулирует запрос в виде объекта, позволяя тем самым параметризовывать клиентов типом запроса, устанавливать очередность запросов,
протоколировать их и поддерживать отмену выполнения операций.
7. Composite (компоновщик)
– Группирует объекты в древовидные структуры для представления
иерархий типа «часть-целое».
– Позволяет клиентам работать с единичными объектами так же, как с
группами объектов.
8. Decorator (декоратор) (173)
– Динамически возлагает на объект новые функции.
– Применяются для расширения имеющейся функциональности и являются
гибкой альтернативой порождению подклассов.
9. Facade (фасад) (183)
– Предоставляет унифицированный интерфейс к множеству интерфейсов в
некоторой подсистеме.
– Определяет интерфейс более высокого уровня, облегчающий работу с
подсистемой.
10. Factory Method (фабричный метод)
– Определяет интерфейс для создания объектов, при этом выбранный класс
инстанцируется подклассами.
11. Flyweight (приспособленец)
– Использует разделение для эффективной поддержки большого числа мелких
объектов.
12. Interpreter (интерпретатор)
– Для заданного языка определяет представление его грамматики, а также
интерпретатор предложений языка, использующий это представление.
13. Iterator (итератор)
– Дает возможность последовательно обойти все элементы составного объекта,
не раскрывая его внутреннего представления.
14. Mediator (посредник)
– Определяет объект, в котором инкапсулировано знание о том, как
взаимодействуют объекты из некоторого множества.
– Способствует уменьшению числа связей между объектами, позволяя им
работать без явных ссылок друг на друга.
– Это, в свою очередь, дает возможность независимо изменять схему
взаимодействия.
15. Memento (хранитель)
– Позволяет, не нарушая инкапсуляции, получить и сохранить
во внешней памяти внутреннее состояние объекта, чтобы
позже объект можно было восстановить точно в таком же
состоянии.
16. Observer (наблюдатель)
– Определяет между объектами зависимость типа один-комногим, так что при изменении состоянии одного объекта
все зависящие от него получают извещение и автоматически
обновляются.
17. Prototype (прототип)
– Описывает виды создаваемых объектов с помощью
прототипа и создает новые объекты путем его копирования.
18. Proxy (заместитель)
– Подменяет другой объект для контроля доступа к нему.
19. Singleton (одиночка)
– Гарантирует, что некоторый класс может иметь только один экземпляр, и
предоставляет глобальную точку доступа к нему.
20. State (состояние)
– Позволяет объекту варьировать свое поведение при изменении внутреннего
состояния. При этом создается впечатление, что поменялся класс объекта.
21. Strategy (стратегия)
– Определяет семейство алгоритмов, инкапсулируя их все и позволяя подставлять
один вместо другого. Можно менять алгоритм независимо от клиента, который
им пользуется.
22. Template Method (шаблонный метод)
– Определяет скелет алгоритма, перекладывая ответственность за некоторые его
шаги на подклассы. Позволяет подклассам переопределять шаги алгоритма, не
меняя его общей структуры.
23. Visitor (посетитель)
– Представляет операцию, которую надо выполнить над элементами объекта.
Позволяет определить новую операцию, не меняя классы элементов, к которым
он применяется.
Скачать