OpenU.Ru
Форма агрегации, при которой части принадлежат
целому, причем время жизни частей совладает со временем жизни композита. Часть
может принадлежать только одному композиту. Части с нефиксированной множественностью
могут быть созданы и после самого композита, однако, будучи созданными, живут
и умирают вместе с ним (иными словами, имеют одинаковое время жизни). Такие
части могут также быть явно удалены еще до смерти композита. Композиция может
быть рекурсивной.
См. aggregation; association;
composite object.
Семантика
У агрегации существует важная форма, которая называется композицией. Композит
- это ассоциация агрегации, у которой есть дополнительные ограничения: объект
может быть одновременно частью только одного композита; объект несет полную
ответственность за размещение всех своих частей. Вследствие первого ограничения,
все множество отношений композиции (то есть все ассоциации, имеющие свойство
композиции) принимает вид множества деревьев из объектов и композиционных связей.
Два композитных объекта не могут иметь одну и ту же композитную часть. Это соответствует
обычному порядку вещей - одна часть не может одновременно служить для создания
двух различных объектов (хотя и может косвенно быть частью нескольких объектов,
находящихся на разных уровнях детализации дерева).
То, что объект несет ответственность за размещение своих частей, означает, что
композит отвечает за их создание и уничтожение. Выражаясь языком реализации;
он отвечает за их размещение в памяти. Во время создания экземпляров композит
должен проверить, были ли созданы экземпляры всех его частей и были ли они после
этого правильно к нему присоединены. Композит может создать часть или
может принять ответственность за уже существующую. Однако пока существует композит,
ни один другой объект не может принять на себя ту же ответственность. Это означает,
что поведение композитного класса можно проектировать, учитывая, что ни один
другой класс не сможет уничтожить или переместить его части. Композит может
добавлять к существующим частям новые (разумеется, если это позволяет множественность
для частей). При этом он принимает ответственность и за эти дополнительные части.
Композит может удалять свои части, опять-таки, если это позволяет множественность
и если ответственность за удалённые части ложится на какой либо другой объект.
Когда же уничтожается весь композит, его части погибают вместе с ним. В противном
случае он должен передавать ответственность за них другому объекту.
Это определение охватывает большую часть способов применения композиции, относящихся
как к логике, так и к реализации. Например, обычным видом реализации объекта
и его атрибутов является запись, у которой есть список значений. При создании
объекта-записи память для её атрибутов выделяется автоматически, однако, значения
этих атрибутов должны быть инициализированы. Пока
существует запись, ни один атрибут не может быть не удалён. При удалении записи
память для неё освобождается, а вместе с ней освобождается и память для атрибутов.
Никакой другой объект не может повлиять на размещение атрибута, принадлежащего
записи. Таким образом, физические свойства записи приводят в действие ограничения
композита.
Такое определение композиции хорошо работает и при сборке мусора. Если композит
уничтожен, указатель на его часть становится неактуальным и тоже подлежит удалению
через сборку мусора. Определение частей, к которым нет доступа, несложно даже
при сборке мусора, и это является одной из причин разделения понятий композиции
и агрегации.
Обратите внимание на то, что часть необязательно реализовывать в виде физической
части одного блока памяти композита. Если она существует отдельно от композита,
то композит несёт ответственность за необходимое размещение и удаление памяти
для этой части. Так, в языке C++ реализация композитов упрощается с помощью
конструкторов и деструкторов.
Объект может быть одновременно частью только одного композита. Это не исключает
того, что в разные моменты времени или в различных экземплярах класс может быть
композитной частью различных классов. При этом для одного объекта может одновременно
существовать только одна композиционная связь. Другими словами, между композитами,
которым может принадлежать часть, существует ограничение "или". Точно
так же один объект в течение своей жизни может быть частью различных композитных
объектов, но не одновременно.
Структура
Свойства агрегации на полюсе ассоциации могут иметь следующие значения:
none (отсутствует) Присоединённый классификатор не является агрегатом или композитом
aggregate (агрегат) Присоединённый классификатор является агрегатом
Другой полюс - часть
composite (композит) Присоединённый компонент является композитом
Другой полюс - часть
По меньшей мере, один из полюсов ассоциации должен иметь значение none.
Нотация
Композиция изображается в виде закрашенного ромба у того полюса ассоциации,
который присоединён к композитному элементу (рис. 68). Множественность указывается
обычным способом: 1 или 0..1.
Существует ещё один вид нотации - графическое размещение символов частей внутри
символа композита (рис. 69).Вложенный классификатор может иметь множественность,
которая изображается в виде строки в верхнем правом углу символа этой части.
В случае, когда знака множественности нет, принято считать, что её значение
равно "many" (много). Вложенный элемент может иметь имя роли в данной
композиции. Это имя указывается в синтаксисе напротив типа:
ИмяРоли : ИмяКласса
Имя роли представляет собой имя роли неявной композиционной ассоциации, идущей
от композита к части.
Ассоциация, целиком, находящаяся целиком внутри композита, считается частью
композиции. Ассоциация, которая выходит за границы композита, не является его
частью. Любые объекты, соединённые связью такой ассоциации, могут принадлежать
как одному, так и различным композитам (рис. 70).
Рис. 68. Нотация композиции
Рис. 69. Композиция в виде графической вставки
Обратите внимание, что в действительности атрибуты являются композиционными
отношениями между классом-владельцем атрибутов и классами, к которым атрибуты
принадлежат (рис. 71). Однако, в целом, атрибуты следует использовать для значений
примитивных данных (чисел, строк, дат), а не для ссылок на классы, так как нотация
атрибутов не может передать всех остальных отношений, которые есть у классов-частей
Рис. 70.
Рис. 71.
Вы, наверное, заметили, что нотация композиции напоминает нотацию кооперации.
Композицию можно представить в виде кооперации, в которой все участники являются
частями одного композитного объекта.
На рис. 72 изображена многоуровневая композиция.
Рис. 72. Многоуровневая композиция
(См. также обсуждение агрегации, в котором содержится
информация о том, когда уместно употребление агрегации, композиции и простой
ассоциации.)
Композиция и агрегация представляют собой метаотношения -они выходят за рамки
отдельных ассоциаций, налагая ограничения на весь ряд ассоциаций. Композиция
выражается посредством композиционных отношений. У объекта может быть максимум
одна действительная композиционная связь (с композитом), хотя потенциально он
может участвовать в нескольких композиционных ассоциациях. Граф, состоящий из
связей композиции и агрегации, должен быть ацикличным, даже в том случае, если
связи происходят из различных ассоциаций. Отметим также, что эти ограничения
относятся к предметной области экземпляров - агрегации часто образуют циклы,
а рекурсивные структуры, вообще, всегда требуют цикличных ассоциаций.
Возьмем модель, изображенную на рис. 73. Каждая Authentication (Авторизация)
представляет собой композитную часть одной Transaction (Транзакции), которая
может быть либо Sale (Покупкой), либо Purchase (Продажей). Однако Transaction
может и не нуждаться в Authentication. Начиная с этого фрагмента, мы можем обоснованно
утверждать, что у Authentication нет никаких других композиционных ассоциаций.
Рис. 73. Композиция дли абстрактного композитного класса
Каждый объект Authentication должен быть частью объекта (множественность равна
единице); объект может являться частью не более чем одного композита (по определению);
он уже является частью композита (как показано на рисунке). Таким образом, Authentication
не может быть частью любой другой композиционной ассоциации. Нет ничего плохого
в том, если Authentication будет управлять своим хранением, так как ответственность
за него всегда может принять на себя Transaction. Впрочем, не у всех Transaction
будут свои Authentication, которыми им нужно будет управлять. (Разумеется,,
Authentication может и не передавать ответственность за хранение - это будет
должным образом спроектировано разработчиком.)
Рис. 74. Класс, являющийся общей частью.
Теперь обратимся к рис. 74. Autograph (Автограф) может быть частью Transaction
(Транзакция), либо частью Letter (Письмо), этом, согласно правилам композиции,
он не может быть одновременно частью обоих. Однако такая модель не запрещает
автографу сначала быть частью письма, а затем стать частью транзакции. (Как
только Autograph станет частью Transaction, он перестанет быть частью Letter.)
В действительности, Autograph может вообще не быть ничьей частью. Основываясь
на имеющемся фрагменте модели, мы не можем исключить возможности того, что Autograph
является необязательной частью какого-либо другого класса, который появится,на
диаграмме позже.
Как же быть в том случае, если необходимо определить, что каждый Autograph (Автограф)
должен являться частью либо Letter (Письмо), либо Transaction (Транзакция)?
В этом случае нужно переформулировать модель, аналогично модели на рис. 73.
Можно добавить новый абстрактный суперкласс (назовем его Document (Документ)).
Тогда композиционная ассоциация автографа перейдет от исходных классов к документу.
При этом множественность от автографа к документу равна единице.
При таком подходе проектирования возникает одна небольшая проблема. Множественность
от документа к автографу должна быть произвольной, что ослабляет обязательное
исходное включение автографа в транзакцию. Подобную ситуацию можно также моделировать,
при помощи обобщения самой композиции, как показано на рис. 75. Композиционная
ассоциация между автографом и
транзакцией моделируется в виде прямого потомка композиционной ассоциации между
автографом и документом. Однако множественность у композиции-прямого потомка
уже определена (не забудьте, что множественность остается совместимой с той
множественностью, которая была унаследована, а значит, прямого потомка можно
подставить на место прямого предка).
Можно, с другой стороны, использовать и исходную модель, добавить к ней ограничение
между двумя композициями, устанавливающее наличие одной из них в любом случае.
Рис. 75. Обобщение композиционной ассоциации