Диаграмма классов uml кратко

Обновлено: 02.07.2024

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

Диаграмма классов UML - это граф, узлами которого являются элементы статической структуры проекта (классы, интерфейсы), а дугами - отношения между узлами (ассоциации, наследование, зависимости).

На диаграмме классов изображаются следующие элементы:

Пакет (package) - набор элементов модели, логически связанных между собой;

Класс (class) - описание общих свойств группы сходных объектов;

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

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

Под поведением объекта в UML понимаются любые правила взаимодействия объекта с внешним миром и с данными самого объекта.

На диаграммах класс изображается в виде прямоугольника со сплошной границей, разделенного горизонтальными линиями на 3 секции:

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

В средней секции содержится список атрибутов

В нижней - список операций класса, отражающих его поведение (действия, выполняемые классом).

Любая из секций атрибутов и операций может не изображаться (а также обе сразу). Для отсутствующей секции не нужно рисовать разделительную линию и как-либо указывать на наличие или отсутствие элементов в ней.

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

Рис. 9. Пример диаграммы классов

Стереотипы классов

Стереотипы классов – это механизм, позволяющий разделять классы на категории.

В языке UML определены три основных стереотипа классов:

Граничные классы

Граничными классами (boundary classes) называются такие классы, которые расположены на границе системы и всей окружающей среды. Это экранные формы, отчеты, интерфейсы с аппаратурой (такой как принтеры или сканеры) и интерфейсы с другими системами.

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

Классы-сущности

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

Управляющие классы

Помимо упомянутых выше стереотипов можно создавать и свои собственные.

Атрибут – это элемент информации, связанный с классом. Атрибуты хранят инкапсулированные данные класса.

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

У атрибута можно определить четыре возможных значения этого параметра:

Package or Implementation (пакетный). Предполагает, что данный атрибут является общим, но только в пределах его пакета. Этот тип видимости не обозначается никаким специальным значком.

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

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

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

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

В языке UML операции имеют следующую нотацию:

Имя Операции (аргумент: тип данных аргумента, аргумент2:тип данных аргумента2. ): тип возвращаемого значения

Следует рассмотреть четыре различных типа операций:

Операции реализации

Операции управления

Операции управления (manager operations) управляют созданием и уничтожением объектов. В эту категорию попадают конструкторы и деструкторы классов.

Операции доступа

Атрибуты обычно бывают закрытыми или защищенными. Тем не менее, другие классы иногда должны просматривать или изменять их значения. Для этого существуют операции доступа (access operations). Такой подход дает возможность безопасно инкапсулировать атрибуты внутри класса, защитив их от других классов, но все же позволяет осуществить к ним контролируемый доступ. Создание операций Get и Set (получения и изменения значения) для каждого атрибута класса является стандартом.

Вспомогательные операции

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

Чтобы идентифицировать операции, выполните следующие действия:

Рассмотрите управляющие операции. Может потребоваться добавить конструкторы и деструкторы.

Рассмотрите операции доступа. Для каждого атрибута класса, с которым должны будут работать другие классы, надо создать операции Get и Set.

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

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

Рис. 10. Связь ассоциация

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

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

Зависимости

Связи зависимости (dependency) также отражают связь между классами, но они всегда однонаправлены и показывают, что один класс зависит от определений, сделанных в другом. Например, класс A использует методы класса B. Тогда при изменении класса B необходимо произвести соответствующие изменения в классе A.

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

Рис. 11. Связь зависимость

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

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

Рис. 11. Связь агрегация

В дополнение к простой агрегации UML вводит более сильную разновидность агрегации, называемую композицией. Согласно композиции, объект-часть может принадлежать только единственному целому, и, кроме того, как правило, жизненный цикл частей совпадает с циклом целого: они живут и умирают вместе с ним. Любое удаление целого распространяется на его части.

Такое каскадное удаление нередко рассматривается как часть определения агрегации, однако оно всегда подразумевается в том случае, когда множественность роли составляет 1..1; например, если необходимо удалить Клиента, то это удаление должно распространиться и на Заказы (и, в свою очередь, на Строки заказа).

Обобщения (Наследование)

Обобщение (наследование) - это отношение типа общее-частное между элементами модели. С помощью обобщений (generalization) показывают связи наследования между двумя классами. Большинство объектно-ориентированных языков непосредственно поддерживают концепцию наследования. Она позволяет одному классу наследовать все атрибуты, операции и связи другого. Наследование пакетов означает, что в пакете-наследнике все сущности пакета-предка будут видны под своими собственными именами (т.е. пространства имен объединяются). Наследование показывается сплошной линией, идущей от класса-потомка к классу-предку (в терминологии ООП - от потомка к предку, от сына к отцу, или от подкласса к суперклассу). Со стороны более общего элемента рисуется большой полый треугольник.

Рис. 12. Пример связи наследование

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

Множественность

Множественность (multiplicity) показывает, сколько экземпляров одного класса взаимодействуют с помощью этой связи с одним экземпляром другого класса в данный момент времени.

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

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

Таблица 1 - Обозначения множественности связей в UML

Имена связей

Рис. 13. Пример имен связей

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

Рис. 14. Пример ролей связей

Пакет. Механизм пакетов

В контексте диаграмм классов, пакет - это вместилище для некоторого набора классов и других пакетов. Пакет является самостоятельным пространством имен.

Рис. 15. Обозначение пакета в UML

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

Пакет физически содержит сущности, определенные в нем (говорят, что "сущности принадлежат пакету"). Это означает, что если будет уничтожен пакет, то будут уничтожено и все его содержимое.

Существует несколько наиболее распространенных подходов к группировке.

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

Другой подход заключается в объединении классов по их функциональности. Например, в пакете Security (безопасность) содержатся все классы, отвечающие за безопасность приложения. В таком случае другие пакеты могут называться Employee Maintenance (Работа с сотрудниками), Reporting (Подготовка отчетов) и Error Handling (Обработка ошибок). Преимущество этого подхода заключается в возможности повторного использования.

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

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

Рис. 16. Пример диаграммы пакетов

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

один класс включает часть данных другого класса; один класс использует другой в качестве параметра операции.

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

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

UML – унифицированный язык моделирования (Unified Modeling Language) – это система обозначений, которую можно применять для объектно-ориентированного анализа и проектирования.
Его можно использовать для визуализации, спецификации, конструирования и документирования программных систем.
Словарь UML включает три вида строительных блоков:

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

Диаграмма – это графическое представление набора элементов, чаще всего изображенного в виде связного графа вершин (сущностей) и путей (связей). Язык UML включает 13 видов диаграмм, среди которых на первом месте в списке — диаграмма классов, о которой и пойдет речь.
Диаграммы классов показывают набор классов, интерфейсов, а также их связи. Диаграммы этого вида чаще всего используются для моделирования объектно-ориентированных систем. Они предназначены для статического представления системы.
Большинство элементов UML имеют уникальную и прямую графическую нотацию, которая дает визуальное представление наиболее важных аспектов элемента.

Сущности

Диаграммы классов оперируют тремя видами сущностей UML:

  • Структурные.
  • Поведенческие.
  • Аннотирующие.

Поведенческие сущности


Аннотирующие сущности – это поясняющие части UML-моделей, иными словами, комментарии, которые можно применить для описания, выделения и пояснения любого элемента модели. Главная из аннотирующих сущностей – примечание . Это символ, служащий для описания ограничений и комментариев, относящихся к элементу либо набору элементов. Графически представлен прямоугольником с загнутым углом; внутри помещается текстовый или графический комментарий.

Аннотирующие сущности

Структурные сущности — классы

Класс – это описание набора объектов с одинаковыми атрибутами, операциями, связями и семантикой.

Графически класс изображается в виде прямоугольника, разделенного на 3 блока горизонтальными линиями:

  • имя класса
  • атрибуты (свойства) класса
  • операции (методы) класса.


Для атрибутов и операций может быть указан один из трех типов видимости:

Видимость для полей и методов указывается в виде левого символа в строке с именем соответствующего элемента.

Обозначение класса

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

Для абстрактного класса имя класса записывается курсивом.


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

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

Статические атрибуты класса обозначаются подчеркиванием.

Операция (метод) – это реализация метода класса. Класс может иметь любое число операций либо не иметь ни одной. Часто вызов операции объекта изменяет его атрибуты.
Графически операции представлены в нижнем блоке описания класса.
Допускается указание только имен операций. Имя операции, как и имя класса, должно представлять собой текст. На практике для именования операции используются короткие глагольные конструкции, описывающие некое поведение класса, которому принадлежит операция. Обычно каждое слово в имени операции пишется с заглавной буквы, за исключением первого, например move (переместить) или isEmpty (проверка на пустоту).
Можно специфицировать операцию, устанавливая ее сигнатуру, включающую имя, тип и значение по умолчанию всех параметров, а применительно к функциям – тип возвращаемого значения.

Абстрактные методы класса обозначаются курсивным шрифтом.
Статические методы класса обозначаются подчеркиванием.

Стереотип

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

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

Существует четыре типа связей в UML:

  • Зависимость
  • Ассоциация
  • Обобщение
  • Реализация

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

Первая из них – зависимость – семантически представляет собой связь между двумя элементами модели, в которой изменение одного элемента (независимого) может привести к изменению семантики другого элемента (зависимого). Графически представлена пунктирной линией, иногда со стрелкой, направленной к той сущности, от которой зависит еще одна; может быть снабжена меткой.

Зависимость


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

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

Пример кода и диаграммы классов для него

Программа получает данные с датчика температуры (вводятся с консоли) — по 5 измерений для каждого из двух объектов класса TemperatureMeasure и усредняет их. Также предусмотрен класс ShowMeasure для вывода измеренных значений.


Результат выполнения

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

На диаграмме классов основным классом является класс TemperatureMeasure , который и является измерителем температуры. В качестве измеренного значения формируется среднее арифметическое всех измерений - сумма всех измерений, деленная на их количество.
Для получения измерений и их суммирования используется класс Sensor (в качестве датчика температуры). В консольной задаче сами измерения передаются в этот класс для суммирования. Класс состоит в отношении агрегации с основным классом TemperatureMeasure : мы сначала создаем объект класса Sensor , а потом передаем его в качестве параметра конструктора классу TemperatureMeasure , чтобы использовать его в качестве части класса.
Количество измерений формируется классом MeasureCount , который содержит статическое свойство total для подсчета общего измерений, а также свойство count для подсчета количества измерителей конкретного объекта TemperatureMeasure . Класс MeasureCount находится в отношении композиции с классом TemperatureMeasure : объект MeasureCount создается непосредственно при создании объекта TemperatureMeasure (в его конструкторе).
Класс ITemperatureMeasure представляет собой интерфейс класса TemperatureMeasure и является своего рода поставщиком в отношении реализации.
Наконец, класс ShowTemperature находится в отношении зависимости с классом TemperatureMeasure , поскольку реализация единственного метода Show класса ShowTemperature зависит от структуры класса TemperatureMeasure .

Класс — это план, который используется для создания объекта. Класс определяет, что может делать объект.

Что такое диаграмма классов?

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

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

Диаграмма классов помогает построить код для разработки программного приложения.

В этом уроке вы узнаете:

Преимущества диаграммы классов

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

Основные элементы диаграммы классов UML

Основные элементы диаграммы классов UML:

  1. Имя класса
  2. Атрибуты
  3. операции

Имя класса


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

При представлении класса необходимо соблюдать следующие правила:

  1. Имя класса всегда должно начинаться с заглавной буквы.
  2. Название класса всегда должно быть в центре первого отсека.
  3. Имя класса всегда должно быть написано жирным шрифтом .
  4. Имя абстрактного класса должно быть написано курсивом.

Атрибуты:

Атрибут именуется свойством класса, который описывает моделируемый объект. На диаграмме классов этот компонент расположен чуть ниже отсека имени.


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


Отношения

В UML есть в основном три вида отношений:

  1. зависимости
  2. Обобщения
  3. ассоциации

зависимость

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

В следующем примере студент имеет зависимость от колледжа


Обобщение:


Обобщение помогает связать подкласс с его суперклассом. Подкласс наследуется от своего суперкласса. Отношение обобщения нельзя использовать для моделирования реализации интерфейса. Диаграмма классов позволяет наследовать от нескольких суперклассов.

В этом примере класс Student обобщается из класса Person.

Ассоциация:

Этот тип отношений представляет статические отношения между классами A и B. Например; сотрудник работает на организацию.

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

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


множественность


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

Допустим, что в одном колледже 100 студентов. Колледж может иметь несколько студентов.

агрегирование

Агрегация — это особый тип ассоциации, который моделирует отношение всей части между агрегатом и его частями.


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

Сочинение:


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

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

Агрегация против состава

агрегирование

Сочинение

Агрегация указывает на отношение, в котором ребенок может существовать отдельно от своего родительского класса. Пример: автомобиль (родитель) и автомобиль (ребенок). Так что, если вы удалите автомобиль, автомобиль ребенка все еще существует.

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

Абстрактные классы

Это класс с прототипом операции, но не с реализацией. Также возможно иметь абстрактный класс без каких-либо операций, объявленных внутри него. Аннотация полезна для определения функциональных возможностей классов. Давайте рассмотрим пример абстрактного класса. Предположим, у нас есть абстрактный класс, называемый движением с методом или операцией, объявленной внутри него. Метод, объявленный внутри абстрактного класса, называется move () .

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

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

Абстрактный класс не может быть инициализирован или создан.


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

Пример диаграммы классов UML

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

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

Ниже приведен пример диаграммы классов UML:

Пример диаграммы классов

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

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

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

2. Перспектива спецификации: Перспектива спецификации описывает программные абстракции или компоненты со спецификациями и интерфейсами. Тем не менее, это не дает никаких обязательств для конкретной реализации.

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

Лучшие практики проектирования диаграммы классов

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

Вот некоторые моменты, которые следует учитывать при рисовании диаграммы классов:

Диаграмма классов занимает центральное место в проектировании объектно-ориентированной системы. Нотация классов используется на разных этапах проектирования и строится с различной степенью детализации. Язык UML применяется не только для проектирования, но и с целью документирования, а также эскизирования проекта. Я (в отличии от Гради Буча) не являюсь сторонником разработки проекта с использованием всех видов UML диаграмм, а также детального проектирования. Чаще всего я применяю UML для эскизирования, а также для проектирования по процессу ICONIX [Rosenberg]. В статье описана часть нотации классов UML, применение которой достаточно в большинстве случаев. Тут не будет информации о кратности ассоциаций и атрибутов, особенностях изображения параллельных операций, шаблонах (параметризованных классах) и ограничениях. При необходимости всю эту информации можно посмотреть в других книгах [Buch, Leonenkov]. Мы же ограничимся базовой частью нотации и больше внимания уделим применению диаграммы классов.

1 Элементы диаграммы классов

На диаграмме классов с помощью специальных символов изображаются типы данных программы и отношения между ними, хотя в некоторых случаях могут использоваться и некоторые другие элементы — пакеты и даже экземпляры классов (объекты) [Leonenkov].

1.1 Символ класса


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

Вопросы детализации будут рассмотрены в следующих разделах, а сейчас надо обратить внимание, что символ класса содержит имя ( Player ), набор операций ( move , get_gealth ) и атрибутов ( pos , state ). Для элементов класса могут задаваться тип, кратность, видимость и т.д.:

Формат спецификации атрибута:
видимость имя : тип [кратность] = значение_по_умолчанию

Формат спецификации операции:
видимость имя(аргумент: тип) = тип_возвращаемого_значения

В зависимости от параметра видимости элемент может быть:

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

1.2 Отношения классов


Диаграмма классов допускает различные виды отношений, рассмотрим их на части диаграммы модели некоторой игры:

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

Отношение композиции обозначается закрашенным ромбом, который рисуется со стороны включающего класса — так, класс MovingItem включает в себя класс Position , т.к. перемещающийся объект всегда имеет позицию. Отношение агрегации изображается незакрашенным ромбом — игрок ( Player ) агрегирует состояние ( IPlayerState ).

Если вы знакомы с паттернами State, Strategy или Delegation — секцию можно пропустить.
На приведенной выше диаграмме используется шаблон проектирования Состояние (State), являющийся разновидностью шаблона Делегирование ( Delegation ) и близкой к паттерну Стратегия ( Strategy ). Суть делегирования заключается в том, что для упрощения логики работы класса, часть его работы может быть передана (делегирована) вспомогательному классу. В свою очередь, паттерн State может быть добавлен, например, на этапе рефакторинга если в нескольких функциях класса встречается разлапистая проверка состояния объекта для выполнения тех или иных действий. В нашем случае персонаж может взаимодействовать с ежом, предположим, что если персонаж движется сидя и контактирует с ежом — у него должно уменьшится здоровье, а если стоя — увеличится счет ( points ). Кроме ежа могла быть еда, противники, патроны и т.д. Для демонстрации такого паттерна создан абстрактный класс IPlayerState и два наследника StayState и SeatState . В классе Player , при нажатии кнопки Ctrl состояние могло бы меняться на SeatState , а при отпускании — на StayState . Таким образом, при выполнении state->process_hedgehog(this) наш игрок каким-то образом, определенным объектом state , проконтактирует с ежиком.

Шаблон проектирования Delegation (и все его разновидности) — хороший пример для демонстрации агрегации. В нашем случае состояние игрока может меняться за счет изменения объекта по указателю, т.е. время жизни объектов различается.

Наиболее общий вид отношений между классами — ассоциация, обозначается сплошной линией (иногда со стрелкой). Вообще, и композиция, и агрегация, и обобщение (наследование) — являются частными случаями ассоциации. В нашей диаграмме с помощью ассоциации показано, что класс IPlayerState изменяет stats ( health и points ) объекта Player . Ассоциация может иметь название связи, поясняющую суть отношения. В качестве названия связей композиции и агрегации часто используется имя соответствующей переменной. Кроме того, ассоциация может иметь кратность, она задается на концах линии:

  • 1 — одна связь (на нашей диаграмме показано, что один игрок включает в себя один экземпляр класса IPlayerState );
  • * любое число связей (если бы на диаграмме был класс игрового поля, то с помощью звездочки можно было бы показать, что оно может содержать произвольное число игровых элементов);
  • [от..до] — может задаваться диапазоном. Так диапазон [0..*] эквивалентен звездочке, но если мы захотим показать, что должно присутствовать более одного объекта — можем записать [1..*]

Последний вид отношений, который мы рассмотрим — зависимость, изображается штриховой (прерывистой) линией. Если есть стрелка — то направлена от зависимого к независимому классу, если стрелки нет — то классы зависят друг от друга. Под зависимостью понимается зависимость от интерфейса, т.е. если интерфейс независимого класса изменится — то придется вносить изменения в зависимый класс. В нашей диаграмме SeatState и StayState зависят от класса Player , т.к. обращаются к его методам для изменения характеристик игрока. Для изображения отношения дружбы между классами используется отношение зависимости с подписью friend .

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

2 Использование диаграммы классов

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

2.1 Диаграмма классов как словарь системы, концептуальная модель

Гради Буч для построения словаря системы предлагает выполнять в следующем порядке [BuchRambo]:

  1. анализируя прецеденты, определить какие элементы пользователи и разработчики применяют для описания задачи или ее решения;
  2. выявить для каждой абстракции соответствующее ей множество обязанностей (ответственности). Проследите правильность распределения обязанностей (в том числе, соблюдение принципа единой обязанности [solid_refactoring]);
  3. разработайте процедуры и операции для выполнения классами своих обязанностей.


В процессе проектирования словарь системы может дополняться, Розенберг очень хорошо демонстрирует это в своей книге описывая итеративный процесс проектирования ICONIX [Rosenberg]. Например, после рассмотрения нескольких прецедентов может оказаться, что несколько классов реализуют один и тот же функционал — для решения проблемы надо более четко прописать обязанности каждого класса, возможно, добавить новый класс и перенести часть этих обязанностей ему.

Ларман предлагает строить концептуальную модель системы [Larman] — это примерно то, что мы описали как словарь системы, но помимо терминов предметной области в ней фиксируются некоторые отношения, понятные заказчику. Например, заказчик понимает (и фиксирует в техническом задании), что оформляет — следовательно, между продавцом и покупкой существует отношение ассоциации "оформляет" . Я рекомендую строить концептуальную модель, дорабатывая словарь системы, хотя Ларман рекомендует сначала добавлять ассоциации, а затем — атрибуты.

2.2 Диаграмма классов уровня проектирования

В любом объектно-ориентированном процессе проектирования диаграмма классов является результатом, т.к. является моделью, наиболее близкой к реализации (коду). Существуют инструменты, способные преобразовать диаграмму классов в код — такой процесс называется кодогенерацией и поддерживается множеством IDE и средств проектирования. Например, кодогенерацию выполняет Visual Paradigm (доступно в виде плагинов для множества IDE), новые версии Microsoft Visual Studio, такие средств UML-моделирования как StarUML, ArgoUML и др. Чтобы построить по диаграмме хороший код, она должна быть достаточно подробной. Именно о такой диаграмме идет речь в этом разделе.

До Ларману [Larman] до начала построения диаграммы классов уровня проектирования должны быть построены диаграммы взаимодействия и концептуальная модель системы. При этом порядок построения диаграммы следующий:

  1. перенести классы с диаграммы последовательности;
  2. добавить атрибуты концептуальной модели;
  3. добавить имена методов по анализу диаграмм взаимодействия (например, диаграмм последовательностей [uml_sequence_diag]);
  4. добавить типы атрибутов и методов;
  5. добавить ассоциации (на основании атрибутов — отношения композиции и агрегации);
  6. добавить стрелки (направление ассоциаций)
  7. добавить ассоциации, определяющие другие виды отношений (в первую очередь, наследование).

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

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

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

2.3 Диаграмма классов для эскизирования, документирования

Сторонником применения UML для эскизирования является Фаулер [Fauler], который считает, что целостный процесс проектирования с использованием UML слишком сложен. Эскизирование применяется очень часто (не только при объяснении проекта на маркерной доске):

  • в любой книге, посвященной паттернам проектирования, вы найдете массу UML диаграмм, выполненных в этом стиле;
  • при моделировании прецедента выбираются классы, за счет которых этот прецедент реализуется. Моделирование прецедента выполняется при рефакторинге;
  • в документацию для разработчиков нет смысла вставлять диаграмму классов уровня проектирования — гораздо полезнее описать наиболее важные (ключевые) моменты системы. Для этого строятся эскизные диаграммы классов и диаграммы взаимодействия. Также существуют специальные инструменты построения документацию по готовому коду — такие как JavaDoc или Doxygen [doxygen_codegeneration], в частности они строят диаграмму классов, но чтобы документация была понятной, в исходный код программы требуется вносить комментарии специального вида.

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

2.4 Диаграмма классов для моделирования БД

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

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

Хранимые между запусками данные должны каким-то образом загружаться по запросу пользователя, т.е. должны задаваться параметры соответствующих классов. Например, приложение должно получить из базы данных список треков (маршрутов) и отобразить его в виде списка в меню программы. При выборе элемента списка — запросить в БД параметры трека, создать объект трека и отобразить его на карте. В любом случае, данные с базы используются при инициализации объектов программы — это важно понимать.

Для моделирования схемы БД с помощью диаграммы классов нужно [Buch_Rambo]:

Заключение и список литературы

В статье я постарался описать наиболее существенные элементы диаграммы классов, а также аспекты их применения. Просматривается, что диаграмма строится на начальном этапе проектирования (концептуальная модель) и является его результатом. На всех этапах проектирования созданная в начале диаграмма классов дорабатывается, т.е. я рассматриваю итеративный процесс (такой как RUP или ICONIX). Кроме того, показано, использование диаграммы классов в других целях — эскизирования, документирования, моделирования логической схемы БД. На других страницах этого блога вы можете найти множество примеров использования диаграммы классов.

Читайте также: