Диаграммы классов являются центральным звеном объектно-ориентированных методов. Диаграмма классов определяет типы объектов системы и различного рода статические связи, которые существуют между ними. Имеются два основных вида статических связей – ассоциации и подтипы.
На диаграммах классов (рис. 2.4.) изображаются также атрибуты классов, операции классов и ограничения, которые накладываются на связи между объектами.
Перед тем как приступить к описанию диаграмм классов, следует обратить внимание на один важный момент, связанный с характером использования этих диаграмм разработчиками. Этот момент обычно никак не документируется, однако оказывает существенное воздействие на способ интерпретации диаграмм и поэтому имеет важное отношение к тому, что описывается с помощью модели. Построение диаграмм классов можно рассматривать в различных аспектах /6/:
- концептуальный аспект – диаграммы классов отображают понятия изучаемой предметной области. Эти понятия, естественно, будут соответствовать реализующим их классам, однако такое прямое соответствие зачастую отсутствует. На самом деле концептуальная модель может иметь весьма слабое отношение или вообще не иметь никакого отношения к реализующему ее ПО, поэтому ее можно рассматривать как независимую от средств реализации (языка программирования);
- аспект спецификации – модель спускается на уровень ПО, но рассматриваются только интерфейсы, а не программная реализация классов (под интерфейсом здесь понимается набор операций класса, видимых извне);
- аспект реализации – модель действительно определяет реализацию классов ПО. Этот аспект наиболее важен для программистов.
Понимание аспекта имеет большое значение как для построения, так и для чтения диаграмм классов. К сожалению, различия между аспектами не столь отчетливы, и большинство разработчиков при построении диаграмм допускают их смешение.
При построении диаграммы необходимо выбрать единственный аспект. При чтении диаграммы следует выяснить, в соответствии с каким аспектом она строилась. Если нужно интерпретировать эту диаграмму правильным образом, то без такого знания не обойтись.
Рис. 2.4. Диаграмма классов
Точка зрения на диаграммы классов при построении и анализе моделей является крайне важной. Большинство опытных программистов предпочитают аспект реализации. Однако построение диаграмм классов на стадии формирования требований к ПО должно выполняться с концептуальной точки зрения.
Ассоциации представляют собой связи между экземплярами классов. С концептуальной точки зрения они представляют собой концептуальные связи между классами.
Каждая ассоциация обладает двумя ролями (двусторонняя связь). Роль может быть явно поименована с помощью метки и обладать множественностью, то есть отражать, сколько объектов может участвовать в данной связи. В общем случае множественность указывает нижнюю и верхнюю границы количества объектов, которые могут участвовать в связи. Символ «*» выражает диапазон «ноль-бесконечность», единица означает диапазон «один-один».
Ассоциации в аспекте спецификации представляют собой ответственности классов.
Диаграмма классов также предполагает, что существуют некоторые механизмы обновления связей.
Если же модель отражает аспект реализации, можно исходить из предположения, что между связанными классами существуют указатели в обоих направлениях. Направление навигации является важной частью диаграмм спецификации и реализации (на концептуальных диаграммах оно отсутствует).
Атрибуты задают имя объекту. В зависимости от степени детальности диаграммы обозначение атрибута может включать имя атрибута, тип и значение. Атрибуты
всегда имеют единственное значение. Обычно на диаграмме не показывается, является атрибут обязательным или необязательным.
Операции представляют собой процессы, реализуемые классом. Наиболее очевидное соответствие существует между операциями и методами над классом. На уровне спецификаций операции соответствуют общим методам над типом. На диаграмме обычно не показывают простые операции манипулирования атрибутами, поскольку они и так подразумеваются. Иногда все же бывает необходимо показать, предназначен ли данный атрибут только для чтения или его значение является постоянным, то есть никогда не изменяется. В модели реализации может также потребоваться отражение уровней секретности и защиты операций.
Полезно проводить границу между операциями, изменяющими состояние класса, и операциями, которые этого не делают. Операция, не изменяющая наблюдаемого состояния класса, результатом которой является некоторое значение, извлекаемое из класса, называется запросом. Наблюдаемым состоянием объекта является состояние, которое можно определить посредством связанных с ним запросов. Операции, изменяющие наблюдаемое состояние объекта, называются модификаторами.
Следует четко понимать разницу между запросами и модификаторами. Запросы могут выполняться в любом порядке, однако последовательность выполнения модификаторов имеет более существенное значение.
Обобщение используется тогда, когда объекты имеют много общего между собой. Оно служит объектом разнообразных интерпретаций в моделях различных уровней. На концептуальном уровне можно утверждать, что объект 1 является подтипом объекта 2, если ассоциации, атрибуты, операции объекта 1 и объекта 2 незначительно заключается между собой. В рамках модели спецификации смысл обобщения заключается в том, что интерфейс подтипа должен включать все элементы интерфейса супертипа. Обобщение в аспекте реализации связано с понятием наследования в языках программирования. Подкласс наследует все методы и поля суперкласса и может переопределять наследуемые методы.
Ограничения используются при построении диаграмм классов. С помощью конструкций ассоциации, атрибута и обобщения можно специфицировать наиболее важные ограничения, но невозможно выразить все ограничения. Они отображаются произвольным образом. Можно использовать неформальную запись ограничений на естественном языке, чтобы их было проще понимать, или использовать более формальные выражения, такие, как исчисление предикатов или производные функции. Другая возможность – это использование фрагментов программного кода.
Диаграммы классов могут содержать множество нотаций, соответствующих различным вспомогательным понятиям. Они используются не столь часто, но в отдельных случаях оказываются весьма удобными. В объектно-ориентированных проектах нередко можно столкнуться с такой ситуацией, когда один класс выполняет практически все функции системы, зачастую посредством одного метода, а другие классы не делают в основном ничего, кроме инкапсуляции данных. Чтобы улучшить такой проект, следует перераспределить функции между незагруженными классами, благодаря чему они станут более интеллектуальными и функционально нагруженными. В связи с этим для принципиальной характеристики класса вводят стереотипы. Оригинальная идея стереотипа заключается в классификации объектов на высоком уровне, дающей некоторое представление о типе каждого объекта. Стереотипы обычно изображаются с помощью текста, заключенного в кавычки, однако они могут также изображаться в виде пиктограммы. Также вводится множественная и динамическая классификация класса. Однозначная классификация подразумевает, что любой объект принадлежит единственному типу, который может наследовать свойства от супертипов. Согласно множе
ственной классификации объект может быть описан несколькими типами, которые не обязательно должны быть связаны наследованием. Несколько подтипов могут характеризоваться одним и тем же дискриминатором. Все подтипы с одним и тем же дискриминатором являются непересекающимися. Это означает, что любой экземпляр супертипа может быть экземпляром только одного из подтипов, описываемых данным дискриминатором. Удачный способ изобразить такое обобщение графически – это свести ассоциации всех подклассов к одной треугольной стрелке с одним дискриминатором. Альтернативный способ – изобразить несколько стрелок с одинаковыми текстовыми метками. Динамическая классификация допускает изменение типа объектов в рамках структуры подтипов, а статическая классификация этого не допускает. Статическая классификация проводит границу между типами и состояниями, а динамическая объединяет эти понятия. Также вводятся понятия агрегация и композиция. Агрегация представляет собой связь «часть-целое» и является одним из наиболее часто используемых приемов моделирования. В дополнение к простой агрегации вводится более сильная ее разновидность – композиция. Согласно композиции объект-часть может принадлежать только единственному целому и, кроме того, как правило, ЖЦ частей совпадает с циклом целого. Любое удаление целого распространяется на его части.