отношения между классами и объектами

Отношения классов — от UML к коду

Введение

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

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. 1 — Отношения между классами

Ассоциации имеют навигацию: двунаправленную или однонаправленную, указывающую на направление связи. То есть у каждого вида ассоциации еще есть два подвида, которое на рисунке не показаны.

1. Обобщение

Итак, наша цель — построить UML-диаграмму классов (Class Model), а затем отразить ее в объектно-ориентированном коде.

В качестве прикладной области возьмем отдел кадров некого предприятия и начнем строить его модель. Для примеров будем использовать язык Java.

Отношение обобщения — это наследование. Это отношение хорошо рассматривается в каждом учебнике какому-либо ООП языку. В языке Java имеет явную реализацию через расширение(extends) одного класса другим.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами
Рис. 2 — Отношение обобщения

Класс «Man»(человек) — более абстрактный, а «Employee»(сотрудник) более специализированный. Класс «Employee» наследует свойства и методы «Man».

Попробуем написать код для этой диаграммы:

2. Ассоциация
2.1 Бинарная

В модель добавили класс «IdCard», представляющий идентификационную карточку(пропуск) сотрудника. Каждому сотруднику может соответствовать только одна идентификационная карточка, мощность связи 1 к 1.
отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами
Рис. 3 — Бинарная ассоциация

В теле программы создаем объекты и связываем их:

Класс Employee имеет поле card, у которого тип IdCard, так же класс имеет методы для присваивания значения(setIdCard) этому полю и для
получения значения(getIdCard). Из экземпляра объекта Employee мы можем узнать о связанном с ним объектом типа IdCard, значит
навигация (стрелочка на линии) направлена от Employee к IdCard.

2.2 N-арная ассоциация

Представим, что в организации положено закреплять за работниками помещения. Добавляем новый класс Room.
Каждому объекты работник(Employee) может соответствовать несколько рабочих помещений. Мощность связи один-ко-многим.
Навигация от Employee к Room.
отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами
Рис. 4 — N-арная ассоциация

Теперь попробуем отразить это в коде. Новый класс Room:

Добавим в класс Employee поле и методы для работы с Room:

2.3 Агрегация

Введем в модель класс Department(отдел) — наше предприятие структурировано по отделам. В каждом отделе может работать один или более человек. Можно сказать, что отдел включает в себя одного или более сотрудников и таким образом их агрегирует. На предприятии могут быть сотрудники, которые не принадлежат ни одному отделу, например, директор предприятия.
отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами
Рис. 5 — Агрегация

Итак, наш класс, помимо конструктора и метода изменения имени отдела, имеет методы для занесения в отдел нового сотрудника, для удаления сотрудника и для получения всех сотрудников входящих в данный отдел. Навигация на диаграмме не показана, значит она является двунаправленной: от объекта типа «Department» можно узнать о сотруднике и от объекта типа «Employee» можно узнать к какому отделу он относится.

Так как нам нужно легко узнавать какому отделу относится какой-либо сотрудник, то добавим в класс Employee поле и методы для назначения и получения отдела.

2.3.1 Композиция

Предположим, что одним из требований к нашей системе является требование о том, чтоб хранить данные о прежней занимаемой должности на предприятии.
Введем новый класс «pastPosition». В него, помимо свойства «имя»(name), введем и свойство «department», которое свяжет его с классом «Department».

Данные о прошлых занимаемых должностях являются частью данных о сотруднике, таким образом между ними связь целое-часть и в то же время, данные о прошлых должностях не могут существовать без объекта типа «Employee». Уничтожение объекта «Employee» должно привести к уничтожению объектов «pastPosition».
отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами
Рис. 6 — Композиция

В класс Employee добавим свойства и методы для работы с данными о прошлой должности:

3. Зависимость

Для организации диалога с пользователем введем в систему класс «Menu». Встроим один метод «showEmployees», который показывает список сотрудников и их должности. Параметром для метода является массив объектов «Employee». Таким образом, изменения внесенные в класс «Employee» могут потребовать и изменения класса «Menu».
отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами
Рис. 7 — Зависимость

Заметим, что класс «Menu» не относится к прикладной области, а представляет собой «системный» класс воображаемого приложения.
Класс «Menu»:

4. Реализация

Реализация, как и наследование имеет явное выражение в языке Java: объявление интерфейса и возможность его реализации каким-либо классом.

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами
Рис. 8 — Реализация

Реализация в классе «Department»:

Как видим, реализация метода «getPersonCount» не совсем актуальна для класса «Department», так как он имеет метод «getEmployees», который возвращает
коллекцию объектов «Employee».

Выводы

Язык моделирования UML имеет набор отношений для построения модели классов, но даже такой развитой ООП язык, как Java имеет только две явные конструкции для отражения связей: extends(расширение) и interface/implements(реализация).
В результате моделирования получили следующую диаграмму:

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами
Рис. 8 — Диаграмма классов

Литература

1) Г. Буч, Д. Рамбо, А. Джекобсон. Язык UML Руководство пользователя.

3) Эккель Б. Философия Java. Библиотека программиста. — СПб: Питер, 2001. — 880 с.

4) Орлов С. Технологии разработки программного обеспечения: Учебник. — СПб: Питер, 2002. — 464 с.

5) Мухортов В.В., Рылов В.Ю.Объектно-ориентированное программирование, анализ и дизайн. Методическое пособие. — Новосибирск, 2002.

Источник

UML для самых маленьких: диаграмма классов

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Аве, Кодер! Диаграмма классов UML иллюстрирует структуру системы, описывая классы, их атрибуты, методы и отношения между объектами.

Даже самые малые детки знают, что UML происходит от Unified Modeling Language, если по- русски, то — унифицированный язык моделирования, который, как гласит легенда, разработали, когда серьезные дяди и тети в конец задолбались плавать в разнообразии кружочков, черточек и облачков.

Для тех, кому лень читать:

Главное действующее лицо

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Для начала напомним себе что такое класс? Если в двух словах, то класс представляет собой шаблон для создания объектов, обеспечивающий начальные значения состояний: инициализацию полей-переменных и реализацию поведения полей и методов.

По сути, класс описывает то, каким объект может быть.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

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

Имя класса пишется в самом верхнем делении, затем идут атрибуты класса, типы которых записываются после двоеточия и, наконец, в нижнем делении идут методы.

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Каждый параметр в методе может также иметь описание направленности метода: in, out, inout.
На этой иллюстрации, method1 использует p1, как входной параметр и значение p1, каким-то образом, используется методом, а метод не изменяет p1.

Method2 принимает p2, как параметр ввода/вывода, значение p2, каким-то образом, используется методом и принимает выходное значение метода, но сам метод также может изменять p2.

Method3 использует p3, как выходной параметр, иными словами, параметр служит хранилищем для выходного значение метода.

Перспективы диаграммы классов в жизненном цикле разработки программного обеспечения

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

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

Типы отношений

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

Ассоциация.
отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Аналогично связям, соединяющим объекты, ассоциации соединяют классы. Для того, чтобы между объектами была связь, между ними должна быть ассоциация.

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

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

Например, один студент может учиться у множества преподавателей.
Но и преподаватель может учить множество студентов.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Или иногда его еще называют — генерализация.

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

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

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

Например, интерфейс Owner имеет методы для покупки и продажи частной собственности, а отношения классов Person и Corporation, реализующих этот интерфейс, на диаграмме будут обозначаться в виде пунктирной линии со стрелкой по направлению к интерфейсу.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

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

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

Например, у класса Person есть метод hasRead с входным параметром book, который возвращает true, если, к примеру, человек прочитал книгу.

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

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

Например, рабочее место программиста состоит из стула, стола, компьютера и вентилятора, но при удалении класса «рабочее место», у нас просто останутся все эти классы, только по отдельности.

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

По сути, разновидность агрегации, только в этом случае, классы, являющиеся частью другого класса, уничтожают, когда уничтожается класс-агрегатор.

Например наше тело состоит из органов, но сами по себе они не жизнеспособны.

Композиция обозначается схожим с агрегацией способом, но ромб на этот раз полностью закрашен.

Финалочка

UML бывает очень полезен для новичков, находящихся на этапе понимания «что к чему долждно идти и от чего наследоваться». Как говорят наши англоязычные коллеги: «он помогает увидеть как выглядит весь лес за стволами деревьев».

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

Источник

Наследование, композиция, агрегация

Нередко случается, что решив разобраться с какой-то новой темой, понятием, инструментом программирования, я читаю одну за другой статьи на различных сайтах в интернете. И, если тема сложная, то эти статьи могут не на шаг не приблизить меня к понимаю. И вдруг встречается статья, которая моментально дает озарение и все паззлы складываются воедино. Трудно определить, что отличает такую статью от других. Правильно подобранные слова, оптимальная логика изложения или же просто более релевантный пример. Я не претендую на то, что моя статься окажется новым словом в C# или же лучшей обучающей статьей. Но, возможно для кого-то она станет именно той, которая позволит разобраться, запомнить и начать правильно применять те понятия, о которых пойдет речь.

В объектно-ориентированных языках программирования существует три способа организации взаимодействия между классами. Наследование — это когда класс-наследник имеет все поля и методы родительского класса, и, как правило, добавляет какой-то новый функционал или/и поля. Наследование описывается словом «является». Легковой автомобиль является автомобилем. Вполне естественно, если он будет его наследником.

Ассоциация – это когда один класс включает в себя другой класс в качестве одного из полей. Ассоциация описывается словом «имеет». Автомобиль имеет двигатель. Вполне естественно, что он не будет являться наследником двигателя (хотя такая архитектура тоже возможна в некоторых ситуациях).

Выделяют два частных случая ассоциации: композицию и агрегацию.

Композиция – это когда двигатель не существует отдельно от автомобиля. Он создается при создании автомобиля и полностью управляется автомобилем. В типичном примере, экземпляр двигателя будет создаваться в конструкторе автомобиля.

Агрегация – это когда экземпляр двигателя создается где-то в другом месте кода, и передается в конструктор автомобиля в качестве параметра.

Хотя ведутся дискуссии о преимуществах того или иного способа организации взаимодействия между классами, какого-либо абстрактного правила не существует. Разработчик выбирает тот или иной путь основываясь на элементарной логике (“является” или “имеет”), но также принимает во внимание возможности и ограничения, которые дают и накладывают эти способы. Для того, чтобы увидеть эти возможности и ограничения, я попытался написать пример. Достаточно простой, чтобы код оставался компактным, но и достаточно развитый, чтобы в рамках одной программы можно было применить все три способа. И, главное, я попытался сделать этот пример как можно менее абстрактным – все объекты и экземпляры понятны и осязаемы.

Напишем простенькую игру – танковый бой. Играют два танка. Они поочередно стреляют и проигрывает тот, здоровье которого упало до нуля. В игре будут различные типы снарядов и брони. Для того, чтобы нанести урон необходимо во-первых, попасть по танку противника, во-вторых, пробить его броню. Если броня не пробита, урон не наносится. Логика игры построена на принципе «камень-ножницы-бумага»: то есть броня одного типа хорошо противостоит снарядам определенного типа, но плохо держит другие снаряды. Кроме того, снаряды, которые хорошо пробивают броню, наносят малый «заброневой» урон, и, напротив, наиболее «летальные» снаряды имеют меньше шансов пробить броню.

Создадим простенький класс для пушки. Он будет иметь два приватных поля: калибр и длину ствола. От калибра зависит урон, и, частично, способность к пробитию брони. От длины ствола – точность стрельбы.

Сделаем также конструктор для пушки:

Сделаем метод для получения калибра из других классов:

Помните, что для поражения цели должно произойти две вещи: попадание в цель и пробитие брони? Так вот, пушка будет отвечать за первую из них: попадание. Поэтому делаем булевый метод IsOnTarget, который принимает случайную величину (dice) и возвращает результат: попали или нет:

Целиком класс пушки выглядит следующим образом:

Здесь мы применили агрегацию. Где-то будет создана пушка. Потом к этой пушке будут создаваться снаряды, которые имеют указатель на пушку.

Теперь сделаем разные типы снарядов, которые будут наследовать абстрактный снаряд: фугасный, кумулятивный, подкалиберный. Фугасный наносит самый большой урон, кумулятивный – меньше, подкалиберный – еще меньше. Дочерние классы не имеют полей и вызывают конструктор базового снаряда, передавая ему пушку, и строковый тип. В дочернем классе переопределяется метод GetDamage() – вносятся коэффициенты, которые увеличат или уменьшат урон по сравнению с дефолтным.

Фугасный (дефолтный урон):

Кумулятивный (дефолтный урон х 0.6):

Подкалиберный (дефолтный урон х 0.3):

Обратите внимание, что в переопределенном методе GetDamage вызывается и метод базового класса. То есть, переопределив метод, мы также сохраняем возможность обратиться к дефолтному методу, использовав ключевое слово base).

Итак, для снарядов мы применили и агрегацию (пушка в базовом классе), и наследование.
Создадим теперь броню для танка. Здесь применим только наследование. Любая броня имеет толщину. Поэтому абстрактный класс брони будет иметь поле thickness, и строковое поле type, которое будет определятся при создании дочерних классов.

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

Для того, чтобы конструктор танка остался более-менее компактным, сделаем два вспомогательных приватных метода, которые добавляют три типа брони соответствующей толщины, и наполняют боеукладку 10 снарядами каждого из трех типов:

Теперь конструктор танка выглядит вот таким образом:

Пользовательский интерфейс танка состоит из трех методов: выбрать броню, зарядить пушку, выстрелить.

Как я упомянул в начале, в этом примере я старался максимально уйти от абстрактных понятий, которые нужно все время держать в голове. Поэтому каждый экземпляр снаряда у нас равен физическому снаряду, который положили в боеукладку перед боем. Следовательно, снаряды могут закончится в самый неподходящий момент!

Этот интерфейс требует реализации метода Clone(). Вот она:

Теперь все супер реалистично: при выстреле генерируется dice, пушка рассчитывает попадание своим методом IsOnTarget, и, если попадание есть, то метод Shoot вернет экземпляр снаряда, а если промах – то вернет null.

Последний метод танка – его поведение при попадании вражеского снаряда:

Все готово. Остается только написать консольный (или неконсольный) вывод, в котором будет обеспечен пользовательский интерфейс и в цикле реализованы поочередные ходы игроков.

Подведем итоги. Мы написали программу, в которой использовали наследование, композицию и агрегацию, надеюсь, поняли и запомнили различия. Активно задействовали возможности полиморфизма, во-первых, когда любые экземпляры дочерних классов можно сложить в список, имеющий тип данных родительского, а во-вторых, создавая методы, которые принимают в качестве параметра родительский экземпляр, но внутри которых вызываются методы дочернего. По ходу текста я упоминал возможные альтернативные реализации – замену наследования на агрегацию, и, универсального рецепта тут нет. В нашей реализации наследование дало нам легкость добавления новых деталей в игру. Например, чтобы добавить новый тип снаряда нам нужно лишь:

Ниже – приведена диаграмма наших классов.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

В финальном коде игры все «магические числа», которые использовались в тексте, вынесены в отдельный статический класс Config. К публичным полям статического класса мы можем обратиться из любого фрагмента нашего кода и его экземпляр не нужно (и невозможно) создавать. Вот так он выглядит:

Источник

Отношения между классами и объектами

Сущности на диаграммах классов связываются главным образом отношениями ассоциации (в том числе агрегирования и композиции) и обобщения. Отношения зависимости и реализации на диаграммах классов применяются реже, но, тем не менее, они также применяются, и мы начнем с них, как с более простых.

3.3.1. Отношения зависимости и реализации

Всего в UML определено довольно большое количество стандартных стереотипов отношения зависимости, которые можно разделить на несколько групп:

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

Табл. Стандартные стереотипы зависимостей на диаграмме классов

СтереотипОписание
«bind»Подстановка параметров в шаблон. Независимой сущностью является шаблон (класс с параметрами), а зависимой ‒ класс, который получается из шаблона заданием аргументов.
«call»Указывает зависимость между двумя операциями: операция зависимого класса вызывает операцию независимого класса.
«derive»Буквально означает «может быть вычислен по». Зависимость с данным стереотипом применяется не только к классам, но и к другим элементам модели: атрибутам, ассоциациям и т.д. Суть состоит в том, зависимый элемент может быть восстановлен по информации, содержащейся в независимом элементе. Таким образом, данная зависимость показывает, что зависимый элемент, вообще говоря, излишен и введен в модель из соображений удобства, наглядности и т.д.
«friend»Назначает специальные права видимости. Зависимый класс имеет доступ к составляющим независимого класса, даже если по общим правилам видимости такие права у него отсутствуют.
«instanceOf»Указывает, что зависимый объект (или класс) является экземпляром независимого класса (метакласса).
«instantiate»Указывает, что операции зависимого класса создают экземпляры независимого класса.
«powertype»Показывает, что экземплярами зависимого класса являются подклассы независимого класса. Таким образом, в данном случае зависимый класс является метаклассом.
«refine»Указывает, что зависимый класс уточняет (конкретизирует) независимый. Данная зависимость показывает, что связанные классы концептуально совпадают, но находятся на разных уровнях абстракции.
«use»Зависимость самого общего вида, показывающая, что зависимый класс каким-либо образом использует независимый класс.

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

Рассмотрим отношение реализации. Между интерфейсами и другими классификаторами, в частности, классами, на диаграмме классов применяются два отношения:

Никаких ограничений на использование отношения реализации не накладывается: класс может реализовывать много интерфейсов, и наоборот, интерфейс может быть реализован многими классами. Нет ограничений и на использование зависимостей со стереотипом «call» ‒ класс может вызывать любые операции любых видимых интерфейсов. Семантика зависимости со стереотипом «call» очень проста ‒ эта зависимость указывает, что в операциях класса, находящегося на независимом полюсе, вызываются операции класса (в частности, интерфейса) находящегося на зависимом полюсе.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Отношения реализации и использования интерфейсов

Используя нотацию «чупа-чупс», появившуюся в UML 2, эту же модель можно изобразить лаконично, симметрично и просто, как показано ниже.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Использование нотации «чупа-чупс»

3.3.2. Отношение обобщения

Отношение обобщения (параграф 1.4.2) часто применяется на диаграмме классов. Действительно, трудно представить себе ситуацию, когда между классами в одной системе нет ничего общего. Как правило, общее есть, и это общее целесообразно выделить в отдельный класс. При этом общие составляющие, собранные в суперклассе, автоматически наследуются подклассами.

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

Принцип подстановки, сформулированный Барбарой Лисков (Liskov substitution principle) заключается в том, что экземпляр подкласса может использоваться везде, где используется экземпляр его суперкласса, поддерживая таким образом контракт, предлагаемый суперклассом. Другими словами, подкласс обеспечивает тот же интерфейс что и суперкласс, т.е. происходит открытое наследование интерфейса.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Отношение обобщения

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

Отношения обобщения можно задавать в UML довольно свободно, но не совсем произвольно. Обобщения в модели должны образовывать строгий частичный порядок.

Таким образом, в UML допускается, чтобы класс был подклассом нескольких суперклассов (множественное наследование), не требуется, чтобы у базовых классов был общий суперкласс (несколько иерархий обобщения) и вообще не накладывается никаких ограничений, кроме частичной упорядоченности (т.е. отсутствия циклов в цепочках обобщений). Нарушение данного условия является синтаксической ошибкой, однако не все инструменты проверяют это условие ‒ цикл может быть незаметен, потому что отдельные дуги цикла обобщений могут быть показаны на разных диаграммах.

При множественном наследовании (multiple inheritance) возможны конфликты: суперклассы содержат составляющие, которые невозможно включить в один подкласс, например, атрибуты с одинаковыми именами, но разными типами. В UML конфликты при множественном наследовании считаются нарушением правил непротиворечивости модели (параграф 1.8.2). Если же конфликты отсутствуют, то множественное наследование в UML не только не запрещается, но даже поощряется! В частности, метамодели в стандарте изобилуют примерами множественного наследования.

Несмотря на те сложности, которые существуют при использовании и в реализации поддержки множественного наследования, его не стоит бояться. Как заметил один из авторов UML (Гради Буч) «проблема множественного наследования находится в головах у архитекторов, а не в языке моделирования».

В UML существует возможность выделять в множестве обобщений подмножества обобщений (generalization set) и задавать ограничения для них.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Подмножества обобщений

Владелец компании (employer) может быть и работником компании (employee).

Табл. Ограничения на подмножество обобщений

ОграничениеПрименение

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

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

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

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

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

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Метамодель отношений зависимости, реализации и обобщения

3.3.3. Ассоциации и их дополнения

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

Связь (link) ‒ это экземпляр ассоциации (или соединителя), который представляет собой упорядоченный набор (кортеж, tuple) ссылок на экземпляры классификаторов на полюсах ассоциации.

Связь между объектами (экземплярами классов) в программе может быть организована самыми разными способами. Например, в объекте одного класса может храниться указатель или ссылка на объект другого класса. Связь не обязательно является непосредственно хранимым физическим адресом. Этот адрес может динамически вычисляться во время выполнения программы на основании другой информации. Например, если объекты представлены как записи в таблице базы данных, то связь означает, что в записи одного объекта имеется поле, значением которого является первичный ключ записи другого объекта (из другой таблицы). Еще пример: использование какого-либо механизма динамического связывания по имени (уникальному идентификатору) объекта. При моделировании на UML техника реализации связи между объектами не имеет значения. Ассоциация в UML подразумевает лишь то, что связанные объекты обладают достаточной информацией для организации взаимодействия. Возможность взаимодействия означает, что объект одного класса может послать сообщение объекту другого класса, в частности, вызвать метод или же прочитать или изменить значение открытого атрибута. Поскольку в объектно-ориентированной программе такого рода действия и составляют суть выполнения программы, моделирование структуры взаимосвязей классов (т.е. выявление ассоциаций) является одной из ключевых задач моделирования.

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

Напомним, что полюсом называется конец линии ассоциации. Обычно используются двухполюсные (бинарные) ассоциации, но могут быть и многополюсные.

Рассмотрим их по порядку.

3.3.4. Имя ассоциации. Кратность полюса ассоциации

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Имя ассоциации и направление чтения

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Кратность полюсов ассоциации

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Использование неопределенной кратности

3.3.5. Агрегация и композиция

В UML используются два частных, но очень важных случая отношения ассоциации, которые называются агрегацией и композицией. В обоих случаях речь идет о моделировании отношения типа «часть ‒ целое». Ясно, что отношения такого типа следует отнести к отношениям ассоциации, поскольку части и целое обычно взаимодействуют.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Отношение агрегации

При этом никаких дополнительных ограничений не накладывается: экземпляр класса Person (часть) может быть связан с другими объектами (т.е. класс Person может участвовать в нескольких агрегациях), создаваться и уничтожаться независимо от экземпляров класса Workgroup (целого).

Однако часть может быть отделена от целого до того, как оно будет удалено. В указанном случае композиция будет разрушена.

Альтернативный способ выражения отношений агрегации и композиции описан в параграфе 3.5.1

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Отношение композиции

При использовании отношения композиция, «целое» часто называют композитом, а при использовании агрегации ‒ агрегатом.

Некоторые инструменты автоматически помещают на диаграмму классов соответствующую линию композиции или агрегации при определении таких атрибутов.

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Структура связей классов информационной системы отдела кадров

Обратите внимание на ассоциацию с именем works for 1 на рисунке выше. Это производная ассоциация.

Производный элемент (derived element) ‒ это элемент, который можно вычислить или определить по другим элементам.

Сделаем еще два важных замечания относительно композиции.

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Пример использования атрибутов

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Пример использования композиции

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Первый вариант реализации сложной композиции

Второй вариант решения состоит в следующем: если у группы классов есть нечто общее, то можно завести абстрактный суперкласс (класс UnitWithBoss ) и установить требуемую композицию с ним.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Второй вариант реализации сложной композиции

Напомним, что ассоциация (и, в частности, композиция) является классификатором, экземплярами которого являются связи, а значит, может участвовать в отношении обобщения.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Третий вариант реализации сложной композиции

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Использование redefines для полюсов ассоциации

3.3.6. Роль полюса ассоциации. Многополюсная ассоциация

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

Роль (role) ‒ это интерфейс, который предоставляет классификатор в данной ассоциации.

Мы надеемся, что туман неясности по поводу понятия «роль» в UML, порожденный нашими постоянными, но неизбежными забеганиями вперед, теперь полностью развеялся.

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

Роль полюса ассоциации (association end role), называемая также спецификатором интерфейса ‒ это способ указать, как именно участвует классификатор (присоединенный к данному полюсу ассоциации) в ассоциации.

Нотация этого дополнения ‒ текст, указанный на полюсе ассоциации. В общем случае роль полюса ассоциации имеет следующий синтаксис:

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Описание иерархии должностей

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Роли полюсов ассоциации

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Атрибуты и операции, обеспечивающие реализацию ролей

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Вариант использования направлений навигации

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Описание иерархии должностей

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Вариант использования направлений навигации

Реальная практика использования свойства возможности навигации показывает, что помимо явной интерпретации (описанной в стандарте), существует и неявная (часто используемая инструментами и подразумеваемая в литературе), а именно, считается, что отсутствие стрелочек на концах линии ассоциации говорит о возможности навигации.

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

Речь идет о матричной структуре управления.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Многополюсная ассоциация

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

3.3.7. Видимость полюса ассоциации. Свойства упорядоченности и уникальности

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Фрагмент диаграммы классов ИС ОК

Другими словами, использование маршрута Person ‒ Company ‒ Department противоречит техническому заданию. Действительно, из приведенного фрагмента модели следует, что потенциально любой работник может получить полную информацию о структуре всего предприятия, на котором он работает.

Рассмотрим маршрут Person ‒ Company ‒ Department еще раз. Каждый их двух участков этого маршрута имеет право на существование. Действительно, работнику не возбраняется знать, на кого он работает (ассоциация между Person и Company ), а компания должна иметь информацию о своей структуре (композиция между Company и Department ). Получается, что навигация по отдельным участкам маршрута Person ‒ Company ‒ Department является допустимой, в то время как на прохождение всего маршрута должно быть наложено ограничение, а точнее говоря, запрет.

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

Видимость полюса ассоциации ‒ это указание того, является ли классификатор, присоединенный к данному полюсу ассоциации, видимым для классификаторов (кроме непосредственно присоединенных), маршруты из которых ведут к нему.

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Пример использования свойства видимости на полюсе ассоциации

Как видно из рассмотренного примера, видимость на полюсе ассоциации может применяться там, где нужна более «точная настройка» чем та, которую обеспечивает свойство возможность навигации (см. параграф 3.3.6).

Закончив с этим дополнением, перейдем к следующим.

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

Ограничения первой группы связаны с понятиями упорядоченности объектов на полюсе ассоциации (ordering) и уникальности (uniqueness), т.е. наличием (отсутствием) в этом множестве одинаковых объектов.

Данные ограничения можно свести в следующую таблицу.

Табл. Свойства упорядоченности и уникальности

Упорядоченное множествоНеупорядоченное множество
Есть одинаковые элементы
последовательность

мультимножество
Нет одинаковых элементов
упорядоченное множество

множество

Обычно считается, что множество объектов на полюсе связи может изменяться произвольным образом (в пределах специфицированной кратности). Например, в один момент работы информационной системы отдела кадров в данном подразделении может быть 10 одних должностей, а в другой ‒ 20 других. Совершенно аналогично, значение атрибута обычно может произвольным образом меняться в процессе жизни объекта (в пределах указанного типа атрибута). Однако иногда необходимо определенным образом ограничить изменяемость атрибута (см. табл. Значения свойства изменяемости атрибутав параграф 3.2.2). Аналогично иногда нужно ограничить изменяемость состава множества объектов присоединенных к полюсу связи (экземпляру ассоциации). Для этого применяется тот же самый набор стандартных значений (еще раз см. табл. Значения свойства изменяемости атрибута).

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Упорядоченность и изменяемость множества объектов на полюсе связи

Вторая группа ограничений появилась только в UML 2 и позволяет манипулировать множествами объектов на полюсах.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Иллюстрация к задаче о восьмиугольнике

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Использование ограничения subsets

На приведенной диаграмме экземпляры класса Polygon хранят исходный массив точек, а экземпляры класса Octagon упорядоченный набор вершин, получаемый после построения выпуклой оболочки, которым и определяются. Ограничение помещенное на полюсе v 1 указывает, что множество вершин восьмиугольника (то есть, фактически, множество объектов на полюсе v ) является подмножеством исходных точек (то есть, фактически, подмножество объектов на полюсе p 2 ).

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Использование ограничения union

3.3.8. Класс ассоциации и квалификатор

В процессе проектирования возможны ситуации, когда ассоциация должна иметь собственные атрибуты (и даже операции), значения которых хранятся в экземплярах ассоциации ‒ связях. В таком случае применяется специальный элемент моделирования ‒ класс ассоциации.

Класс ассоциации (association class) ‒ это сущность, которая является ассоциацией, но также имеет в своем составе составляющие класса.

Класс ассоциации изображается в виде символа класса, присоединенного пунктирной линией к линии ассоциации.

Вернемся к информационной системе отдела кадров.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Класс ассоциации

Может показаться, что понятие класса ассоциации в UML является надуманным и излишним. Действительно, можно применить стандартный прием нормализации, который часто используется при проектировании схем баз данных: систематическим образом избавиться от отношений «многие ко многим» путем введения дополнительной сущности 1 и трех отношений «один ко многим». Применительно к данному примеру такой прием дает решение, приведенное на следующем рисунке.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Элиминация отношения «многие ко многим» с помощью введения дополнительной сущности

Для того чтобы решить задачу поиска конкретного сотрудника (конкретный экземпляр класса Person ) всегда можно применить следующее тривиальное решение: хранить ключ (ИНН) в самом объекте класса Person в качестве атрибута и, получив множество объектов, перебирать их все последовательно до тех пор, пока не найдется тот, который имеет искомое значение ключа. Такой прием называется линейным поиском. Для компаний, в которых не очень много сотрудников, данный способ может быть вполне приемлемым. Но в других случаях, когда к полюсу с кратностью «много» присоединено действительно много объектов, линейный поиск слишком неэффективен. Известно множество структур данных, позволяющих эффективно выделить (найти в множестве) объект по ключу: сортированные массивы, таблицы расстановки (хэш-таблицы), деревья сортировки, внешние индексы и др. Эти приемы обобщены в UML понятием квалификатора.

Квалификатор полюса ассоциации (qualifier) ‒ это атрибут (или несколько атрибутов) полюса ассоциации, значение которого (которых) позволяет выделить один (или несколько) объектов класса, присоединенного к другому полюсу ассоциации.

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

Основное назначение квалификатора ‒ снизить кратность противоположного полюса ассоциации, поэтому в основном он используется в ассоциациях с кратностями полюсов «один ко многим» или «многие ко многим» и стоит у полюса противоположному полюсу с кратностью «много».

При использовании квалификатора кратность противоположного полюса снижается, и это отображается на диаграмме.

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

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

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Метамодель ассоциации

3.3.9. Советы по проектированию

Нам хочется закончить обсуждение диаграмм классов ‒ важнейшего средства описания структуры в UML ‒ серией элементарных советов по практическому моделированию структуры. Как видно из предыдущих разделов, диаграммы классов содержат множество деталей. Для практически значимых систем диаграммы классов в конечном итоге получаются довольно сложными. Пытаться прорисовать сложную диаграмму классов сразу «на всю глубину» нерационально ‒ слишком велик риск «утонуть» в деталях. Мы полагаем, что удачная модель структуры сложной системы создается за несколько (может быть, даже за несколько десятков) итераций, в которых моделирование структуры перемежается моделированием поведения (см. главу 4). Вот наши советы.

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

отношения между классами и объектами. Смотреть фото отношения между классами и объектами. Смотреть картинку отношения между классами и объектами. Картинка про отношения между классами и объектами. Фото отношения между классами и объектами

Рис. Основная диаграмма классов ИС ОК

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *