Джим Арлоу, Айла Нейштадт - UML 2 и Унифицированный процесс. Практический объектно-ориентированный анализ и проектирование (1037782), страница 73
Текст из файла (страница 73)
CPU, в свою очередь, может быть смоделированкак совокупность различных аппаратных компонентов, таких как RAM(ОЗУ), HardDrive (жесткий диск) и т. д.39718.5. Семантика композицииHomeComputer11Mouse1KeyboardCPU12MonitorSpeaker1*1RAM1..*FloppyDrive1HardDriveCDRom2connectedTo11SoundCardGraphicsCard11connectedToРис. 18.7. Типичный пример агрегации: компьютер как совокупность его частей18.5. Семантика композицииКомпозиция – более строгая форма агрегации. Она имеет сходную(но более ограниченную) семантику. Как и агрегация, это отношение целоечасть, являющееся как транзитивным, так и асимметричным.Ключевое различие между агрегацией и композицией в том, что в композиции у частей нет независимой жизни вне целого. Более того, в композиции каждая часть принадлежит максимум одному и только одному целому, тогда как при агрегации часть может совместно использоваться несколькими целыми.Композиция – это строгая форма агрегации.В примере на рис.
18.8 объекты Button (кнопка) не могут существоватьнезависимо от владеющего ими объекта Mouse. Если уничтожаетсяобъект Mouse, уничтожаются и принадлежащие ему объекты Button,потому что они являются его неотъемлемой частью. Каждый объектButton может принадлежать только одному объекту Mouse. Так же и листья на деревьях – жизнь листа определяется жизнью дерева, и листможет принадлежать только одному дереву.всегда 0..1 или 111..4MouseкомпозитButtonкомпозицияРис. 18.8. Пример композициичасть398Глава 18. Уточнение отношений, выявленных при анализеКомпозит имеет исключительное право владения и ответственностиза свои части.Резюмировать семантику композиции можно следующим образом:•одновременно части могут принадлежать только одному композиту –совместное владение частями невозможно;•композит обладает исключительной ответственностью за все своичасти; это означает, что он отвечает за их создание и уничтожение;•композит может высвобождать части, передавая ответственностьза них другому объекту;•в случае уничтожения композита он должен или уничтожить всесвои части, или передать ответственность за них другому объекту.Поскольку композит обладает исключительной ответственностью зажизненный цикл и управление своими частями, то при создании объект композита часто создает и свои части.
Аналогично при уничтожении композита он должен уничтожить все свои части или организовать их передачу другому композиту.Несмотря на то, что существуют и иерархии, и сети рефлексивной агрегации, для рефлексивной композиции возможны только иерархии.В этом состоит еще одно отличие между агрегацией и композицией,которое объясняется тем, что в композиции объектчасть в любой момент времени может быть частью только одного композита.18.5.1. Композиция и атрибутыЧасть композита эквивалентна атрибуту.Рассматривая семантику композиции, можно заметить, что она оченьпохожа на семантику атрибутов.
Жизненный цикл в обоих случаяхконтролируется владельцами. И части, и атрибуты не могут независимо существовать вне своих владельцев. В сущности, атрибуты – этоточный эквивалент отношения композиции между классом композитаи классом атрибута. Тогда зачем нужны два способа описания одногои того же? На это есть две причины:•Типом атрибута может быть простой тип данных. В некоторых гибридных ОО языках программирования, таких как C++ и Java, естьпростые типы, например int и double, которые не являются классами. Их можно было бы моделировать как классы, обозначенныестереотипом «primitive», но это загромождало бы модель.
Простыетипы всегда должны моделироваться как атрибуты.•Существуют определенные, широко используемые утилитные классы, такие как Time, Date и String. Если бы каждый раз приходилосьмоделировать эти классы с помощью отношения композиции класса18.6. Как уточнять отношения уровня анализа399с самим собой, очень скоро модели стали бы абсолютно непонятными. Намного лучше моделировать такие классы как атрибуты.Вывод состоит в следующем: если имеется простой тип, или утилитный класс, или даже класс, который не стоит явно показывать в модели, поскольку он не представляет особого интереса либо от него малопользы, необходимо рассмотреть возможность применения атрибута,а не отношения композиции.
Здесь нет никакого конкретного и твердого правила, но главное, о чем надо всегда помнить, – это понятность,полезность и удобочитаемость модели.18.6. Как уточнять отношения уровня анализаПри анализе использовались простые ассоциации без какоголибо подробного рассмотрения семантики отношения (или того, каким образом отношение должно быть реализовано).
Однако при проектировании необходимо всегда пытаться достичь максимальной конкретизации и уточнить ассоциации до одного из отношений агрегации везде,где это возможно. Фактически ассоциация должна использоватьсяв проектировании, только если в противном случае в схеме агрегацииобразуется цикл (см. раздел 18.4). Такая ситуация встречается редко,поэтому большинство аналитических ассоциаций превращаются илив агрегацию, или в композицию.Аналитические ассоциации должны быть уточнены до одного из отношений агрегации везде, где это возможно.После того как принято решение о применении агрегации или композиции, необходимо действовать следующим образом:•добавить в ассоциации кратности и имена ролей, если они отсутствуют;•выбрать, какой конец ассоциации является целым, а какой – частью;•посмотреть на кратность связи со стороны целого; если это 0..1 или 1,вероятно, можно использовать композицию; в противном случаедолжна использоваться агрегация;•добавить возможность навигации от целого к части – ассоциацииуровня проектирования должны быть однонаправленными.Таким образом, происходит уточнение ассоциации до агрегации иликомпозиции.Если кратности целого или части больше 1, необходимо принять решение, как это будет реализовываться.
Это второй шаг уточнения.400Глава 18. Уточнение отношений, выявленных при анализе18.7. Ассоциации одинкодномуПрактически всегда ассоциация одинкодному превращается в композицию. По сути, ассоциация одинкодному подразумевает настолькострогое отношение между двумя классами, что зачастую стоит рассмотреть возможность их объединения в один класс без нарушения правилпроектирования для проектных классов (раздел 17.5).
Если классынельзя объединить, отношение одинкодному уточняется до композиции, как показано на рис. 18.9.анализParty11PartyIdentifier«trace»1проектирование1PartyPartyIdentifierРис. 18.9. Ассоциация один+к+одному уточняется до композицииОбычно ассоциации одинкодному подразумевают композицию.Также можно было бы рассмотреть возможность превращения PartyIdentifier (идентификатор партии) в атрибут класса Party (партия), еслиPartyIdentifier не является особо важным классом. Это, конечно, упрощает диаграмму (рис. 18.10), но имеет и недостаток: нельзя показатьатрибуты или операции, принадлежащие классу PartyIdentifier.анализParty11PartyIdentifier«trace»проектированиеPartyid:PartyIdentifierРис. 18.10. Класс PartyIdentifier превращен в атрибут класса Party18.8.
Ассоциации многиекодномуВ ассоциации многиекодному целое имеет кратность «много», а кратность части равна 1.40118.9. Ассоциации одинBкоBмногимцелоеанализMoneyчасть*1Currency«trace»проектированиеMoney*1CurrencyРис. 18.11. Ассоциация многие+к+одному уточняется до агрегацииПоскольку со стороны целого кратность равна «много», сразу понятно, что композиции невозможна, потому что часть используется совместно многими целыми. Но, вероятно, возможна агрегация. Здесьнеобходимо провести проверку на наличие циклов в схеме агрегации(см. раздел 18.4). Если таковых не обнаружено, аналитическую ассоциацию можно уточнять до агрегации, как показано на рис. 18.11.Как видно из этого примера, один объект Currency (валюта) совместноиспользуется многими объектами Money (деньги). Это абсолютно верноотражает отношение между деньгами и валютой: деньги – это суммав некоторой валюте.
Намного более полную модель денег можно найтив книге [Arlow 1].Ассоциации многиекодному подразумевают агрегацию, если в схемеагрегации нет цикла.18.9. Ассоциации одинкомногимВ ассоциации одинкомногим со стороны части присутствует коллек+ция объектов. Чтобы реализовать такое отношение, необходимо использовать или поддержку коллекций, предоставляемую языком реализации, или классыколлекции.Большинство ОО языков программирования имеют минимальнуювстроенную поддержку коллекций объектов.
В сущности, большинствоязыков предлагают только массивы. Массив – это индексированнаяколлекция объектных ссылок, обычно ограниченная некоторым максимальным размером. Преимущество встроенных массивов, как правило,состоит в их высокой производительности. Однако это преимуществонивелируется их малой гибкостью в сравнении с другими типами коллекций.Классыколлекции обычно характеризуются намного большей мощьюи гибкостью, чем массивы.
Они предлагают разнообразные семантики,в которых массив является лишь одним из возможных вариантов. Далее вся глава посвящена классамколлекций.402Глава 18. Уточнение отношений, выявленных при анализе18.10. КоллекцииКлассколлекции – это класс, экземпляры которого специализируются на управлении коллекциями других объектов. В большинстве языков программирования есть стандартные библиотеки классовколлекций (и других утилит).Классыколлекции – это классы, экземпляры которых содержат коллекции объектов.Одним из ключей к отличному ОО проектированию и реализации является совершенное владение классамиколлекций.
У всех таких классовесть операции для:• добавления объектов в коллекцию;• удаления объектов из коллекции;• извлечения ссылки на объект, находящийся в коллекции;• обход коллекции, т. е. проход по коллекции от первого объекта до последнего.Существует много типов коллекций, поразному обрабатывающих коллекции объектов. Важным аспектом ОО проектирования и реализацииявляется правильный выбор типа коллекции (обсуждается далее).В качестве примера использования коллекций на рис.
18.12 показанаассоциация одинкомногим уровня анализа, реализованная с помощью классаколлекции Vector. Это класс стандартной библиотеки Javajava.util. Как правило, между целым (классом Order (заказ)) и классомVector устанавливается отношение композиции, поскольку Vector обычно является всего лишь частью реализации целого и не может существовать вне него. Однако между классом Vector и его частями (OrderLine(строка заказа)) может существовать отношение агрегации или композиции. Если целое несет ответственность за жизненный цикл частей,как в данном примере, можно использовать композицию.