В качестве примера рассмотрим следующие варианты задания кратности атрибутов.
   [0..1] означает, что кратность атрибута может принимать значение О или 1. При этом 0 означает отсутствие значения для данного атрибута.
   [0..*] означает, что кратность атрибута может принимать любое положительное целое значение большее или равное 0. Эта кратность может быть записана короче в виде простого символа – [*].
   [1.:*] означает, что кратность атрибута может принимать любое положительное целое значение большее или равное 1.
   [1..5] означает, что кратность атрибута может принимать любое значение из чисел: 1, 2, 3, 4, 5.
   [1..3,5,7] означает, что кратность атрибута может принимать любое значение из чисел: 1, 2, 3, 5, 7.
   [1..3,7.. 10] означает, что кратность атрибута может принимать любое значение из чисел: 1, 2, 3, 7, 8, 9, 10.
   [1..3,7..*] означает, что кратность атрибута может принимать любое значение из чисел: 1, 2, 3, а также любое положительное целое значение большее или равное 7.
   Если кратность атрибута не указана, то по умолчанию принимается ее значение равное 1..1, т. е. в точности 1.
   Тип атрибута представляет собой выражение, семантика которого определяется языком спецификации соответствующей модели. В нотации UML тип атрибута иногда определяется в зависимости от языка программирования, который предполагается использовать для реализации данной модели. В простейшем случае тип атрибута указывается строкой текста, имеющей осмысленное значение в пределах пакета или модели, к которым относится рассматриваемый класс.
   Можно привести следующие примеры задания имен и типов атрибутов классов:
   • цвет: Соlоr – здесь цвет является именем атрибута, Color – именем типа данного атрибута. Указанная запись может определять традиционно используемую RGB-модель (красный, зеленый, синий) для представления цвета. В этом случае имя типа Color как раз и характеризует семантическую конструкцию, которая применяется в большинстве языков программирования для представления цвета.
   • имя_сотрудника [1..2] : String – здесь имя_сотрудника является именем атрибута, который служит для представления информации об имени, а возможно, и отчестве конкретного сотрудника. Тип атрибута String (Строка) как раз и указывает на тот факт, что отдельное значение имени представляет собой строку текста из одного или двух слов (например, «Кирилл» или «Дмитрий Иванович»). Поскольку во многих языках программирования существует тип данных String, использование соответствующего англоязычного термина не вызывает недоразумения у большинства программистов. Однако, хотя в языке UML все термины даются в англоязычном представлении, использование в качестве типа атрибута Строка в данной ситуации не исключается и определяется только соображениями удобства.
   • видимость:Boolean – здесь видимость есть имя абстрактного атрибута (курсив здесь не случаен), который может характеризовать наличие визуального представления соответствующего класса на экране монитора. В этом случае тип Boolean означает, что возможными значениями данного атрибута является одно из двух логических значений: истина (true) или ложь (false). При этом значение истина может соответствовать наличию графического изображения на экране монитора, а значение ложь – его отсутствию, о чем дополнительно указывается в пояснительном тексте. Поскольку кратность атрибута видимость не указана, она принимает значение 1 по умолчанию. В этой ситуации англоязычное имя типа атрибута вполне оправдано наличием соответствующего базового типа в языках программирования. Абстрактный характер данного атрибута обозначается курсивным текстом в записи данного атрибута.
   • форма:Многоугольник – здесь имя атрибута форма может характеризовать такой класс, который является геометрической фигурой на плоскости. В этом случае тип атрибута Многоугольник указывает на тот факт, что отдельная геометрическая фигура может иметь форму треугольника, прямоугольника, ромба, пятиугольника и любого другого многоугольника, но не окружности или эллипса. Вполне очевидно, что в данной ситуации использование соответствующего англоязычного термина вряд ли целесообразно, поскольку тип Многоугольник не является базовым для языков программирования.
   Исходное значение служит для задания некоторого начального значения для соответствующего атрибута в момент создания отдельного экземпляра класса. Здесь необходимо придерживаться правила принадлежности значения типу конкретного атрибута. Если исходное значение не указано, то значение соответствующего атрибута не определено на момент создания нового экземпляра класса. С другой стороны, конструктор соответствующего объекта может переопределять исходное значение в процессе выполнения программы, если в этом возникает необходимость.
   В качестве примеров исходных значений атрибутов можно привести следующие дополненные выше варианты задания атрибутов:
   • цвет:Соlоr = (255, 0, 0) – в RGB-модели цвета это соответствует чистому красному цвету в качестве исходного значения для данного атрибута.
   • имя_сотрудника[1..2]:String = Иван Иванович – возможно, это нетипичный случай, который, скорее, соответствует ситуации имя_руководителя[2]:81пп§ = Иван Иванович.
   • видимость:Вооlеаn = истина – может соответствовать ситуации, когда в момент создания экземпляра класса создается видимое на экране монитора окно, соответствующее данному объекту.
   • форма:Многоугольник = прямоугольник – вряд ли требует комментариев, поскольку здесь речь идет о геометрической форме создаваемого объекта.
   При задании атрибутов могут быть использованы две дополнительные синтаксические конструкции – это подчеркивание строки атрибута и пояснительный текст в фигурных скобках.
   Подчеркивание строки атрибута означает, что соответствующий атрибут может принимать подмножество значений из некоторой области значений атрибута, определяемой его типом. Эти значения можно рассматривать как набор однотипных записей или массив, которые в совокупности характеризуют каждый объект класса.
   Например, если некоторый атрибут задан в виде форма: Прямоугольник.то это будет означать, что все объекты данного класса могут иметь несколько различных форм, каждая из которых является прямоугольником. Другим примером может служить задание атрибута в виде номер_счета:Integer. что может означать для объекта Сотрудник наличие некоторого подмножества счетов, общее количество которых заранее не фиксируется.
   Строка-свойство служит для указания значений атрибута, которые не могут быть изменены в программе при работе с данным типом объектов. Фигурные скобки как раз и обозначают фиксированное значение соответствующего атрибута для класса в целом, которое должны принимать все вновь создаваемые экземпляры класса без исключения. Это значение принимается за исходное значение атрибута, которое не может быть переопределено в последующем. Отсутствие строки-свойства по умолчанию трактуется так, что значение соответствующего атрибута может быть изменено в программе. Например, строка-свойство в записи атрибута заработная_плата:Currency = = {$500} может служить для обозначения фиксированной заработной платы для каждого объекта класса «Сотрудник» определенной должности в некоторой организации. С другой стороны, запись данного атрибута в виде зара-ботная_плата: Currency = $500 означает уже нечто иное, а именно – при создании нового экземпляра Сотрудник (аналогия – прием на работу нового сотрудника) для него устанавливается по умолчанию заработная плата в $500. Однако для отдельных сотрудников могут быть сделаны исключения как в большую, так и в меньшую сторону, о чем необходимо позаботиться дополнительно в программе.

Операция

   В третьей сверху секции прямоугольника записываются операции или методы класса. Операция (operation) представляет собой некоторый сервис, предоставляющий каждый экземпляр класса по определенному требованию. Совокупность операций характеризует функциональный аспект поведения класса. Запись операций класса в языке UML также стандартизована и подчиняется определенным синтаксическим правилам. При этом каждой операции класса соответствует отдельная строка, которая состоит из квантора видимости операции, имени операции, выражения типа возвращаемого операцией значения и, возможно, строка-свойство данной операции:
   <квантор видимости><имя операции>(список параметров):
   <выражение типа возвращаемого значения>{строка-свойство}
   Квантор видимости, как и в случае атрибутов класса, может принимать одно из трех возможных значений и, соответственно, отображается при помощи специального символа. Символ "+" обозначает операцию с областью видимости типа общедоступный (public). Символ "#" обозначает операцию с областью видимости типа защищенный (protected). И, наконец, символ "-" используется для обозначения операции с областью видимости типа закрытый (private).
   Квантор видимости для операции может быть опущен. В этом случае его отсутствие просто означает, что видимость операции не указывается. Вместо условных графических обозначений также можно записывать соответствующее ключевое слово: public, protected, private.
    Примечание 46
   Имя операции представляет собой строку текста, которая используется в качестве идентификатора соответствующей операции и поэтому должна быть уникальной в пределах данного класса. Имя атрибута является единственным обязательным элементом синтаксического обозначения операции.
   Список параметров является перечнем разделенных запятой формальных параметров, каждый из которых может быть представлен в следующем виде:
   <вид параметра><имя параметра>:<выражение типа>=<значение параметра по умолчанию>.
   Здесь вид параметра – есть одно из ключевых слов in, out или inout со значением in по умолчанию, в случае если вид параметра не указывается. Имя параметра есть идентификатор соответствующего формального параметра. Выражение типа является зависимой от конкретного языка программирования спецификацией типа возвращаемого значения для соответствующего формального параметра. Наконец, значение по умолчанию в общем случае представляет собой выражение для значения формального параметра, синтаксис которого зависит от конкретного языка программирования и подчиняется принятым в нем ограничениям.
   Выражение типа возвращаемого значения также является зависимой от языка реализации спецификацией типа или типов значений параметров, которые возвращаются объектом после выполнения соответствующей операции. Двоеточие и выражение типа возвращаемого значения могут быть опущены, если операция не возвращает никакого значения. Для указания кратности возвращаемого значения данная спецификация может быть записана в виде списка отдельных выражений.
   Строка-свойство служит для указания значений свойств, которые могут быть применены к данному элементу. Строка-свойство не является обязательной, она может отсутствовать, если никакие свойства не специфицированы.
   Операция с областью действия на весь класс показывается подчеркиванием имени и строки выражения типа. По умолчанию под областью операции понимается объект класса. В этом случае имя и строка выражения типа операции не подчеркиваются.
   Операция, которая не может изменять состояние системы и, соответственно, не имеет никакого побочного эффекта, обозначается строкой-свойством «{запрос}» («{query}»). В противном случае операция может изменять состояние системы, хотя нет никаких гарантий, что она будет это делать.
   Для повышения производительности системы одни операции могут выполняться параллельно или одновременно, а другие – только последовательно. В этом случае для указания параллельности выполнения операции используется строка-свойство вида «{concurrency = имя}», где имя может принимать одно из следующих значений: последовательная (sequential), параллельная (concurrent), охраняемая (guarded). При этом придерживаются следующей семантики для данных значений:
   • последовательная (sequential) – для данной операции необходимо обеспечить ее единственное выполнение в системе, одновременное выполнение других операций может привести к ошибкам или нарушениям целостности объектов класса.
   • параллельная (concurrent) – данная операция в силу своих особенностей может выполняться параллельно с другими операциями в системе, при этом параллельность должна поддерживаться на уровне реализации модели.
   • охраняемая (guarded) – все обращения к данной операции должны быть строго упорядочены во времени с целью сохранения целостности объектов данного класса, при этом могут быть приняты дополнительные меры по контролю исключительных ситуаций на этапе ее выполнения.
   С целью сокращения обозначений допускается использование одного имени в качестве строки-свойства для указания соответствующего значения параллельности. Отсутствие данной строки-свойства означает, что семантика параллельности для операции не определена. Поэтому следует предположить худший с точки зрения производительности случай, когда данная операция требует последовательного выполнения.
   Появление сигнатуры операции на самом верхнем уровне объявляет эту операцию на весь класс, при этом данная операция наследуется всеми потомками данного класса. Если в некотором классе операция не выполняется (т. е. некоторый метод не применяется), то такая операция может быть помечена как абстрактная «{abstract}». Другой способ показать абстрактный характер операции – записать ее сигнатуру курсивом. Подчиненное появление записи данной операции без свойства {абстрактная} указывает на тот факт, что соответствующий класс-потомок может выполнять данную операцию в качестве своего "метода.
   Если для некоторой операции необходимо дополнительно указать особенности ее реализации (например, алгоритм), то это может быть сделано в форме примечания, записанного в виде текста, который присоединяется к записи операции в соответствующей секции класса. Если объекты класса принимают и реагируют на некоторый сигнал, то запись данной операции помечается ключевым словом «сигнал» («signal»). Это обозначение равнозначно обозначению некоторой операции. Реакция объекта на прием сигнала может быть показана в виде некоторого автомата. Кроме других случаев эта нотация может быть использована, чтобы показать реакцию объектов класса на ошибочные ситуации или исключения, которые могут моделироваться как сигналы или сообщения.
   Поведение операции может быть указано дополнительно в форме присоединенного к операции примечания. В этом случае текст примечания заключается в скобки, если он представляет собой формальную спецификацию на некотором языке программирования и соответствует элементу «семантическое ограничение языка UML». В противном случае текст примечания является простым описанием на естественном языке и обозначается прямоугольником с «загнутым» верхним правым уголком (см. главу 4).
   Список формальных параметров и тип возвращаемого значения могут не указываться. Квантор видимости атрибутов и операций может быть указан в виде специального значка или символа, которые используются для графического представления моделей в некотором инструментальном средстве. Имена операций, так же как и атрибутов, записываются со строчной (малой) буквы, а их типы – с заглавной (большой) буквы. При этом обязательной частью строки записи операции является наличие имени операции и круглых скобок.
   В качестве примеров записи операций можно привести следующие обозначения отдельных операций:
   • +создать() – может обозначать абстрактную операцию по созданию отдельного объекта класса, которая является общедоступной и не содержит формальных параметров. Эта операция не возвращает никакого значения после своего выполнения.
   • +нарисовать(форма: Многоугольник = прямоугольник, цвет_заливки: Color = (О, О, 255)) – может обозначать операцию по изображению на экране монитора прямоугольной области синего цвета, если не указываются другие значения в качестве аргументов данной операции.
   • запросить_счет_клиента(номер_счета:1п1е§ег):Сиггепсу – обозначает операцию по установлению наличия средств на текущем счете клиента банка. При этом аргументом данной операции является номер счета клиента, который записывается в виде целого числа (например, «123456»). Результатом выполнения этой операции является некоторое число, записанное в принятом денежном формате (например, $1,500.00).
   • выдать_сообщение():{"Ошибка деления на ноль"} – смысл данной операции не требует пояснения, поскольку содержится в строке-свойстве операции. Данное сообщение может появиться на экране монитора в случае попытки деления некоторого числа на ноль, что недопустимо.

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

   Кроме внутреннего устройства или структуры классов на соответствующей диаграмме указываются различные отношения между классами. При этом совокупность типов таких отношений фиксирована в языке UML и предопределена семантикой этих типов отношений. Базовыми отношениями или связями в языке UML являются:
   • Отношение зависимости (dependency relationship)
   • Отношение ассоциации (association relationship)
   • Отношение обобщения (generalization relationship)
   • Отношение реализации (realization relationship)
   Каждое из этих отношений имеет собственное графическое представление на диаграмме, которое отражает взаимосвязи между объектами соответствующих классов.

Отношение зависимости

   Отношение зависимости в общем случае указывает некоторое семантическое отношение между двумя элементами модели или двумя множествами таких элементов, которое не является отношением ассоциации, обобщения или реализации. Оно касается только самих элементов модели и не требует множества отдельных примеров для пояснения своего смысла. Отношение зависимости используется в такой ситуации, когда некоторое изменение одного элемента модели может потребовать изменения другого зависимого от него элемента модели.
   Отношение зависимости графически изображается пунктирной линией между соответствующими элементами со стрелкой на одном из ее концов («->» или «<-»). На диаграмме классов данное отношение связывает отдельные классы между собой, при этом стрелка направлена от класса-клиента зависимости к независимому классу или классу-источнику (рис. 5.3). На данном рисунке изображены два класса: Класс_А и Кяасс_Б, при этом Класс_Б является источником некоторой зависимости, а Класс_А – клиентом этой зависимости.
    Рис. 5.3.Графическое изображение отношения зависимости на диаграмме классов
   В качестве класса-клиента и класса-источника зависимости могут выступать целые множества элементов модели. В этом случае одна линия со стрелкой, выходящая от источника зависимости, расщепляется в некоторой точке на несколько отдельных линий, каждая из которых имеет отдельную стрелку для класса-клиента. Например, если функционирование Класса_С зависит от особенностей реализации Класса_А и Класса_/>, то данная зависимость может быть изображена следующим образом (рис. 5.4).
    Рис. 5.4.Графическое представление зависимости между классом-клиентом (Класс_С) и классами-источниками (Класс_Л и Класс_Б)
   Стрелка может помечаться необязательным, но стандартным ключевым словом в кавычках и необязательным индивидуальным именем. Для отношения зависимости предопределены ключевые слова, которые обозначают некоторые специальные виды зависимостей. Эти ключевые слова (стереотипы) записываются в кавычках рядом со стрелкой, которая соответствует данной зависимости. Примеры стереотипов для отношения зависимости представлены ниже:
   • «access» – служит для обозначения доступности открытых атрибутов и операций класса-источника для классов-клиентов;
   • «bind» – класс-клиент может использовать некоторый шаблон для своей последующей параметризации;
   • «derive» – атрибуты класса-клиента могут быть вычислены по атрибутам класса-источника;
   • «import» – открытые атрибуты и операции класса-источника становятся частью класса-клиента, как если бы они были объявлены непосредственно в нем;
   • «refine» – указывает, что класс-клиент служит уточнением класса-источника в силу причин исторического характера, когда появляется дополнительная информация в ходе работы над проектом.
    Примечание 47

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

   Отношение ассоциации соответствует наличию некоторого отношения между классами. Данное отношение обозначается сплошной линией с дополнительными специальными символами, которые характеризуют отдельные свойства конкретной ассоциации. В качестве дополнительных специальных символов могут использоваться имя ассоциации, а также имена и кратность классов-ролей ассоциации. Имя ассоциации является необязательным элементом ее обозначения. Если оно задано, то записывается с заглавной (большой) буквы рядом с линией соответствующей ассоциации.
   Наиболее простой случай данного отношения – бинарная ассоциация. Она связывает в точности два класса и, как исключение, может связывать класс с самим собой. Для бинарной ассоциации на диаграмме может быть указан порядок следования классов с использованием треугольника в форме стрелки рядом с именем данной ассоциации. Направление этой стрелки указывает на порядок классов, один из которых является первым (со стороны треугольника), а другой – вторым (со стороны вершины треугольника). Отсутствие данной стрелки рядом с именем ассоциации означает, что порядок следования классов в рассматриваемом отношении не определен.
   В качестве простого примера отношения бинарной ассоциации рассмотрим отношение между двумя классами – классом «Компания» и классом «Сотрудник» (рис. 5.5). Они связаны между собой бинарной ассоциацией Работа, имя которой указано на рисунке рядом с линией ассоциации. Для данного отношения определен порядок следования классов, первым из которых является класс «Сотрудник», а вторым – класс «Компания». Отдельным примером или экземпляром данного отношения может являться пара значений (Петров И. И., «Рога&Копыта»). Это означает, что сотрудник Петров И. И. работает в компании «Рога&Копыта».
    Рис. 5.5.Графическое изображение отношения бинарной ассоциации между классами
   Тернарная ассоциация и ассоциации более высокой арности в общем случае называются N-арной ассоциацией (читается – «эн арная ассоциация»). Такая ассоциация связывает некоторым отношением 3 и более классов, при этом один класс может участвовать в ассоциации более чем один раз. Класс ассоциации имеет определенную роль в соответствующем отношении, что может быть явно указано на диаграмме. Каждый экземпляр N-арной ассоциации представляет собой N-арный кортеж значений объектов из соответствующих классов. Бинарная ассоциация является частным случаем N-арной ассоциации, когда значение N=2, и имеет свое собственное обозначение.
   N-арная ассоциация графически обозначается ромбом, от которого ведут линии к символам классов данной ассоциации. В этом случае ромб соединяется с символами соответствующих классов сплошными линиями. Обычно линии проводятся от вершин ромба или от середины его сторон. Имя N-арной ассоциации записывается рядом с ромбом соответствующей ассоциации.
   Порядок классов в N-арной ассоциации, в отличие от порядка множеств в отношении, на диаграмме не фиксируется. Некоторый класс может быть присоединен к ромбу пунктирной линией. Это означает, что данный класс обеспечивает поддержку свойств соответствующей N-арной ассоциации, а сама N-арная ассоциация имеет атрибуты, операции и/или ассоциации. Другими словами, такая ассоциация, в свою очередь, является классом с соответствующим обозначением в виде прямоугольника и является самостоятельным элементом языка UML – ассоциацией-классом (Association Class). N-арная ассоциация не может содержать символ агрегации ни для какой из своих ролей.
   В качестве примера конкретной тернарной ассоциации рассмотрим отношение между тремя классами: «Футбольная команда», «Год» и «Игра». Данная ассоциация указывает на наличие отношения между этими тремя классами, которое может представлять информацию об играх футбольных команд в национальном чемпионате в течение нескольких последних лет (рис. 5.6).
   Как уже упоминалось, отдельный класс ассоциации имеет собственную роль в отношении. Эта роль может быть изображена графически на диаграмме классов. С этой целью в языке UML вводится в рассмотрение специальный элемент – конец ассоциации (Association End), который графически соответствует точке соединения линии ассоциации с отдельным классом. Конец ассоциации является частью ассоциации, но не класса. Каждая ассоциация имеет два или больше концов ассоциации. Наиболее важные свойства ассоциации указываются на диаграмме рядом с этими элементами ассоциации и должны перемешаться вместе с ними.