Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методы и средства проектирования информационных систем и технологий. Основы UML. Учебное пособие.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Рис. 2.5. Выборочные перечисления
В примечании, прикрепленном к Visibility Kind, указаны стандартные сим­волы, используемые в UML для определения видимости функции.
Индикатор VisibilityKind является примером обзначения для атрибутов или операций.
В спецификации UML все имена типов перечисления заканчиваются на «Kind», как показано на Visibility Kind (рис. 2.5). На рисунке 2.6 показано, что мы включили как Traffic Li ght Color Kind, так и Traffic Light Colour Kind для поддержки сигналов трафика как в США, так и в Великобритании. Перечис­ленные литералы имеют идентичность только внутри перечисления. Если вы попытались проверить на равенство между значениями зелёного светофора, вы можете или не можете заставить их отображаться как равные, или вы можете просто получить ошибку типа. Если вы хотите ссылаться на каждый цвет неза­висимо, используйте оператор области именования ".".
Перечисленные литералы неизменны. Мы не можем изменить значение любого из литералов, поэтому они не могут появляться в левой части оператора присваивания или как возвращаемое или выходное значение операции. Тем не менее, они могут использоваться для установки значения атрибута или пере­менной или проверяться на равенство/равенство.
31
Рис. 2.6. Унаследованные перечисления
Мы не рассматриваем внутреннее представление перечислений. Это могут быть строки, целые числа, начинающиеся с единицы, целые числа, начинаю­щиеся с нуля, или что-то еще. Некоторые инструменты могут позволять указы­вать значения или порядок литералов для генерации кода, но это не является частью текущего UML.
Использование только этих нескольких примитивных типов и перечисле­ний очень ограничено. UML предлагает возможность создавать дополнитель­ные типы на основе примитивов. Они выглядят как классы, за исключением то­го, что они используют ключевое слово «dataType». На рисунке 2.7 показано два сконструированных типа данных. Мы также использовали «+», публичную видимость, чтобы указать, что свойства и операции dataType видны вне
dataType.
Также были добавлены некоторые операции к типу даты datatType, чтобы поддержать добавление дней к текущей дате и сравнение дат. Результат первой операции addToDate (days: Integer) не нуждаётся в возвращаемом значении, по­тому что эта операция обновляет значение DateType.
На рисунке 2.7 ограничения помещены на ту же строку, что и свойство с ограничениями. Также, в случае, когда в блоке не хватает места их можно раз­местить в отдельном блоке, который называется «ограничения». Справа и на рис. 2.8 использован формальный формат:
Во всех случаях ограничения заключены в фигурные скобки.
32
Рис. 2.7. Два пользовательских типа данных
Рис. 2.8. Блок «ограничения»
Хороший тип (data Type или class) поддерживает абстракции. В этом кон­тексте абстракция представляет собой единую концепцию, которая освобожде­на от физических деталей или деталей реализации, а использование сокрытия информации скрывает эти детали, чтобы предотвратить злоупотребление или раскрытие деталей. Сокрытие деталей с помощью таких методов, как инкапсу­ляция, будет способствовать переносимости.
Например, если бы мы создали класс Stack, возможно, реализованный с помощью списка, мы бы не хотели, чтобы пользователь мог дополнительно ус­танавливать или получать какие-либо элементы списка, кроме установленных разработчиком (рис. 2.9).
33
Рис. 2.9. Класс Stack
Некоторые разработчики моделей стереотипируют data Type как Abstract DataType (или ADT). Это не является частью стандарта, но это полезно. «Abstract Data Type» объявляет, что вы предоставили или запретили все необ-
ходимые операции для поддержания согласованности типа. ADT имеет в виду некоторые математические или архитектурные абстракции.
В подходе к реализации класса Stack, список скрыт от внешней стороны, и определены только «безопасные» операции.
Атрибут или операцию можно отметить определённым модификатором, который изменяет некоторую, обычно незначительную, интерпретацию компо­нента.
На рисунке 2.10 изображён класс Member, который использует данные ти­па Full Name и Date.
Каждый экземпляр Member имеет атрибут name. Если необходим сослать­ся на first Name текущего участника, это будет current Member.name. first Name. Если требуется указать год, в котором родился текущий участник, это будет
current Member.birthdate.year.
Рис. 2.10. Класс, использующий пользовательские data Types
34
Существует ещё один атрибут для Member, hasAdultPrivileges типа Boolean. Если вы посмотрите внимательно, вы увидите, что перед именем атри-
бута стоит косая черта. Это имеет особое значение в UML, оно указывает, что значение атрибута является производным. Значение производного атрибута может быть вычислено по необходимости на основе других атрибутов или дос­тупных свойств.
Во многих библиотеках материал делится по возрастным категориям. Мы устанавливаем видимость для name, hasAdultPrivileges и isAdult () как public (+), что означает, что любой может просматривать значения этих атрибутов или вы­зывать операцию. Мы сохранили дату рождения как конфиденциальную, по­скольку она, вероятно, будет идентифицирующей личность информацией, т.е. в соответствии с законодательством должна быть защищена от разглашения. Не­смотря на то, что дата рождения является частной (–), она доступна в операции isAdult (), поэтому она может вычислить значение свойства hasAdultPrivileges.
До того, как экземпляр Member собирается заимствовать книгу с ограни­чением по возрасту, должна быть вызвана операция isAdult (). Результат будет присвоен has Adult Privileges. Как только экземпляр Member объявлен как соот­ветствующий возрасту, операцию isAdult () больше вызывать не требуется. Бу­левыми свойствами или операциями принято называть форму has Property или isInState, чтобы использование значений True или False было естественно.
Также для свойства возможно назначить значение по умолчанию. На ри­сунке 2.11 мы модифицируем логический флаг hasAdultPrivleges, чтобы иметь значение по умолчанию False. Это означает, что всякий раз, когда мы создаем новый экземпляр Member, флагу будет присваиваться начальное значение False.
Рис. 2.11. Иллюстрация значения по умолчанию (начального значения) и readOnly
35
В этом случае всякий раз, когда читатель пытается взять книгу для взрос­лых, мы проверяем значение флага. Если поле имеет значение False, мы бы вы­звали операцию isAdult (). Если читатель является взрослым, тогда мы устанав­ливаем флаг, чтобы в следующий раз, когда читатель попытается взять книгу для взрослых, мы увидим, что читатель уже имеет разрешение.
Значение по умолчанию должно быть того же типа, что и базовый атрибут.
Обратите внимание, что хотя поле даты рождения помечено как частное (–), это значение доступно внутри для операций над элементом. Следовательно, операция isAdult () может прочитать поле даты рождения.
Также возможно присвоить значение по умолчанию аргументам операции. На рисунке 2.12 мы предоставляем логическое значение по умолчанию, исполь­зуя логический литерал False для аргумента isRenew. Нам нужно изменить ар­гумент a только одновременно с обновлением книги.
Есть моменты, когда мы хотим, чтобы область была защищена от измене­ний. Мы можем сделать свойство частным, что исключит только те изменения, которые происходят вне экземпляра. Если требуется большая защита, можно добавить к этому свойству {readOnly}. Это указывает на то, что свойство долж­но быть защищено от всех изменений после его инициализации. На рисунке
2.11 мы пометили дату рождения участников как {readOnly}. На практике это может быть слишком строго. Нередко нужно исправлять неко­торые поля в случае случайных или намеренных ошибок ввода.
В большинстве инструментов readOnly не поддерживается сгенерирован­ным кодом, поэтому рекомендуется сделать свойство закрытым.
Как и во многих свойствах, имя свойства является сокращенной формой для isReadOnly = True. Значение по умолчанию для isReadOnly – False.
36
Рис. 2.12. Пример аргумента с присвоением значения по умолчанию
{query} – это операция, которой не разрешено изменять какие-либо значе­ния атрибутов экземпляра. Пометка операции как query, также как и пометка атрибута readOnly, указывает на то, что единственное, что изменяется после операции, это возвращаемое значение.
Это, как и isReadOnly, является возможностью моделирования и не всегда обеспечивается сгенерированным кодом (рис. 2.13) для использования {query}.
Использование {query} на рисунке указывает на то, что операция isAdult () не изменит какой-либо атрибут элемента или что-либо еще, кроме возврата ло­гического значения. Запрос – это свойство операции, которое отображается как обозначение {query}.
Параметры для операции могут быть помечены их предполагаемым на­правлением. Существует четыре возможных значения перечисления для на­правления параметров. Значение по умолчанию, используемое для ParameterDirectionKind, если не указано иное, – «in». Крайний правый столбец в таблице указывает, когда значения параметра заслуживают доверия, для пара­метра «in» или «inout» должны быть заданы значения, прежде чем они будут переданы в поведение / операцию. Параметры, отмеченные как «out», «inout» или «return», будут иметь новые значения после вызова, и любое ранее уста­новленное значение будет потеряно во время вызова.
На рисунке 2.14 первые два параметра – «в». Следующий параметр, Дебет, представляет стоимость предстоящей поездки, однако, в зависимости от остат­ка на кредитной карте, он может быть только частично финансируемым (требу-
Рис. 2.13. Операция {query}
37
Рис. 2.14. Пример работы с использованием Parameter Direction Kind
ется дополнительный источник финансирования). В этом случае приложение оставляет остаток в параметре дебетования, и success Flag будет установлен в значение false. Поэтому мы устанавливаем их флаги направления на «inout» и «out» соответственно. Мы резервируем Return Type для более серьезных сбоев, таких как не обнаружение кредитной карты, ввод-вывод или сетевые ошибки. Подходы, которые вызывают исключения, также возможны, но здесь не рас­сматриваются.
Обычная практика – упорядочивать параметры по их направлению (ис­пользуя порядок «in», «inout», «out» и «return»). Поскольку «in» является значе­нием по умолчанию, оно часто опускается. Также обычно опускается направле­ние вида «return», потому его обычно можно узнать по месту в конце вызова операции.
Когда мы назначаем значение по умолчанию (начальное) атрибуту класса или значение слоту в экземпляре, мы можем использовать значение Literal. Мы уже использовали многие из них раньше. Например, на рис. 3.16 мы использо­вали целочисленные литералы для установки значения для полей даты. На ри­сунке 2.15 мы использовали строковый литерал для присвоения значения полю заголовка.
38
Рис. 2.15. Класс и экземпляр
Рассмотрим обозначение, возможности и особенности спецификации объ­екта/экземпляра.
Давайте сначала различим объекты, экземпляры и характеристики экземп­ляров. «Объект» – это либо элемент реального мира (M1), либо элемент кода/ реализации (M0). «Экземпляр» – это то же самое, с упором на тот факт, что здесь задействован класс или тип (классификатор), т.е. «экземпляр» класса.
На рисунке 2.15 мы видим спецификацию экземпляра с именем myBook, которая представляет экземпляр класса Book, который в настоящее время назы­вается myBook, у которого есть слот заголовка, содержащий «Tom Sawyer». Спецификация экземпляра – это элемент модели (обычно с соответствующими элементами диаграммы), который обычно обозначает экземпляр, но может обо­значать один из набора экземпляров. Например, если существует много книг с названием «Tom Sawyer», Спецификация экземпляра может относиться к лю­бому из совместимых экземпляров.
Можно подумать, что спецификация экземпляра похожа на класс. Однако класс обозначает набор экземпляров, а спецификация экземпляра определяет один из потенциально меньшего набора. В UML 2.5 спецификация экземпляра представляет собой прямоугольную рамку с отсеком для имени и дополнитель­ным отсеком для слота. Раздел имени включает подчеркнутое имя, в приведён­ном выше случае это myBook, за которым следует ":", а затем имя класса, эк­земпляром которого являются экземпляры, в данном случае Book.
Все поля, кроме ":", необязательны. Если вы не указываете класс, специ­фикация экземпляра указывает, что класс не важен, и подойдет экземпляр лю­бого класса. Если вы не укажете имя, то имя экземпляра не имеет значения. Раздел имени также может отображать любые соответствующие стереотипы.
Под отделением имени находятся слоты. Они представляют атрибуты из класса с необязательными буквальными значениями, которые являются значе­ниями для этих атрибутов в текущий момент. Литеральное значение должно
39
быть совместимо с типами атрибутов. Часто типы атрибутов повторяются после имени слота, как показано ниже:
title: String = «Tom Sawyer»
Можно добавить дополнительный блок ограничений, чтобы фиксировать любые ограничения в этом экземпляре. Нет отсеков операций и сигналов. Эле­менты, которые будут в этих отсеках, будут отражены в определении класса, и их не нужно будет повторять. Точно так же в отсеке для слотов не повторяйте слоты, если вы действительно не заботитесь об их значениях в данном случае.
Дополнительный блок ограничений может быть добавлен для захвата лю­бых ограничений в этом случае. Там нет операций или сигналов отсеков. Эле­менты, которые будут находиться в этих отсеках, будут включены в определе­ние класса и не должны повторяться. Точно так же, в разделе слотов, не повто­ряйте слоты, если вы действительно не заботитесь об их значениях в этом случае.
Следует различать имя экземпляра и значение любого конкретного атрибу­та. Например, мы могли бы изменить определение класса, чтобы оно имело ат­рибут name: String, и соответственно изменить слот заголовка на слот имени. В таком случае имя экземпляра по-прежнему будет «myBook», а атрибут имени экземпляра – «TomSawyer».
В приведённом ниже примере (рис. 2.16), мы показываем myBDate как эк­земпляр даты dataType. Как и в случае с классами, мы не показываем никаких операций, а просто дублируем определения типа. Пунктирная стрелка, которую мы используем для соединения двух элементов (рис. 2.15, 2.16), – это необяза­тельная стрелка зависимости, указывающая, что экземпляры зависят от опреде­ления их класса или типа.
Можно использовать литерал или косвенный литерал через спецификацию экземпляра, чтобы присвоить значение свойству или слоту, как мы видели,
40
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]