Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
UML.doc
Скачиваний:
214
Добавлен:
10.05.2015
Размер:
2.54 Mб
Скачать

5.8 Зависимость между пакетами

Зависимости можно устанавливать не только между классами, но и между пакетами. Фактически, это единственный тип связей, существующий между пакетами. Как и в случае классов, зависимость между пакетами изображают пунктирной линией.

Отношение зависимости между пакетами А и В означает, что некоторый класс пакета А связан однонап­равленным отношением с некоторым классом пакета В. Иначе говоря, класс из пакета А должен знать что-либо о классе из пакета В.

Зависимости определяют возможность повторного использования пакетов. Зависимость пакета А от пакета В означает, что при создании других приложений пакет А можно использовать только совместно с пакетом В. Однако сам пакет В можно использовать повторно, так как он не зависит ни от чего больше.

Зависимости между пакетами можно обнаружить, исследуя отношения на диаграмме классов. Если два класса из различных пакетов связаны, эти пакеты также связаны.

Создавая зависимости между пакетами, старайтесь по мере возможности избегать циклических за­висимостей. Такая зависимость предполагает, что класс из пакета А должен знать о классе из пакета В, а еще ка­кой-то класс пакета В должен знать о классе из пакета А. Следовательно, ни один пакет нельзя само­стоятельно использовать повторно, и изменения в одном из них неизбежно повлияют на другой. Таким образом, теряется одно из преимуществ пакетов - они становятся слишком взаимозависимы.

Чтобы разбить циклическую зависимость, разделите пакет на два. В нашем примере можно взять классы пакета В, от которых зависит А, и переместить их в третий пакет С. Тогда зависимости паке­тов будут выглядеть так, как показано на рис. 5.6.

Рисунок 5.6. Зависимость между пакетами.

5.9 Отношение ассоциации

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

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

В качестве простого примера отношения бинарной ассоциации рассмотрим отношение между двумя классами — классом "Компания" и классом "Сотрудник" , как показано на рис. 5.7. Они связаны между собой бинарной ассоциацией Работа, имя которой указано на рисунке рядом с линией ассоциации. Для данного отношения определен порядок следования классов, первым из которых является класс "Сотрудник", а вторым — класс "Компания". Отдельным примером или экземпляром данного отношения может являться пара значений (Петров И. И., "Сиеста-металл"). Это означает, что сотрудник Петров И. И. работает в компании "Сиеста-металл".

Рисунок 5.7. Графическое изображение отношения бинарной ассоциации между классами

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

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

Так, для рассмотренного примера, приведенного на рис. 5.7 кратность "1" для класса "Компания" означает, что каждый сотрудник может работать только в одной компании. Кратность "1..*" для класса "Сотрудник" означает, что в каждой компании могут работать несколько сотрудников, общее число которых заранее неизвестно и ничем не ограничено. Заметим, что вместо кратности "1..*" записать только символ "*" нельзя, поскольку последний означает кратность "0..*". Для данного примера это означало бы, что отдельные компании могут совсем не иметь сотрудников в своем штате.

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

Частным случаем отношения ассоциации является так называемая исключающая ассоциация (Xor-association). Семантика данной ассоциации указывает на тот факт, что из нескольких потенциально возможных вариантов данной ассоциации в каждый момент времени может использоваться только один ее экземпляр. На диаграмме классов исключающая ассоциация изображается пунктирной линией, соединяющей две и более ассоциации, рядом с которой записывается строка-ограничение "{Xor}".

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

Рисунок 5.8. Графическое изображение исключающей ассоциации между тремя классами

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

С точки зрения кодогенерации наличие на диаграмме отношения ассоциации указывает на возможность одного класса узнавать об общих атрибутах и операциях другого класса. Например, на рис. 5.9 показана двунаправленная ас­социация между классами Дом и Жилец.

Класс Жилец знает об общих атрибутах и операциях Дома, а Дом - об общих атрибутах и операци­ях Жильца. Таким образом, на диаграммах последовательности Дом может посылать сообщения Жи­льцу, и наоборот.

Рисунок 5.9 Двунаправленная ас­социация между классами Дом и Жилец: классы могут обмениваться сообщениями

В приведенном примере отношение ассоциации - двунаправленное. Однако ассоциации можно сделать и однонап­равленными. Такими отношениями легче управлять, и проще обнаружить классы, допускающие повторное использование. На рис. 5.10 показана однонаправленная ассоциация.

Рисунок 5.10. Ассоциация, направленная от класса Жилец к классу Дом.

В этом случае Жилец знает об общих атрибутах и операциях Дома, но Дом не знает об атрибутах и операциях Жильца. Сообщения на диаграммах последовательности и кооперации могут отправляться Жильцом и приниматься Домом, но не наоборот.

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

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

При генерации кода для двунаправленной ассоциации создаются дополнительные атрибуты у каж­дого класса. В нашем примере атрибут класса Жилец будет помещен внутри Дома, а атрибут класса Дом внутри Жильца. Ниже приведен код на Java, сгенерированный для этих двух классов.

Программный код для класса Жилец:

public class Person

{

public House m_House;

public Person() {}

}

Программный код для класса Дом:

public class House

{

public Person m_Person;

public House() {}

}

В случае однонаправленной ассоциации атрибут Дом будет помещен внутри Жильца, но не наобо­рот. Ниже приведен код для однонаправленной ассоциации.

Программный код для класса Жилец:

public class Person

{

public House m_House;

public Person() {}

}

Программный код для класса Дом:

public class House

{

public House() {}

}

Ассоциации могут быть рефлексивными. Рефлексивная ассоциация предполагает, что один экзем­пляр класса взаимодействует с другими экземплярами этого же класса. Рассмотрим класс Жилец.

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

Для отношения "один к одному" кодогенераторы обычно создают атрибуты, необходимые для поддержки ассо­циации: в одном классе должен содержаться набор элементов друго­го класса. Рассмотрим пример, приведенный на рис. 5.11.

Рисунок 5.11. Ненаправленная ассоциация, роли классов в которой сгенерированы по умолчанию.

Программный код, генерируемый для приведенного отношения, имеет следующий вид.

Программный код для Class_A:

public class Class_A

{

public Class_B theClass_B[];

public Class_A() {}

}

Программный код для Class_B:

public class Class_B

{

public Class_A theClass_A;

public Class_B() {}

}

Здесь в классе Class_B просто содержится атрибут, имеющий тип Class_A. Но поскольку множественность гово­рит о том, что каждому экземпляру класса Class_А соответствует несколько экземпляров класса Class_B, то внутри класса Class_A создается массив объектов класса Class_B.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]