Концепция: Структурированный класс
Структурированным классом называется класс, состоящий из "вложенных компонентов" и применяемый для моделирования иерархических систем вложенных объектов, т.е. классов, состоящих из "компонентов".
Взаимосвязи
Связанные элементы
Основное описание

Определение

В рамках UML ([UML04]) классы (Class) представляют собой подтип EncapsulatedClassifier и метакласса Class одновременно, благодаря чему у объектов Class могут быть внутренняя структура и порты. Кроме того, компоненты в UML представляют собой подтип типа Class. Таким образом, в контексте RUP как компоненты, так и классы представляют собой структурированные классы.

Компонент

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

На следующем примере показаны два представления класса Car:

На рисунке (a) у класса Car составная связь в роли rear с классом Wheel и составная связь с ролью e с классом Engine. Любой экземпляр класса Engine можно привязать к произвольному количеству экземпляров класса Wheel.

На рис. (b) показана та же самая ситуация. Однако на рис. (b) в дополнение к прежним данным указаны следующие сведения:

  • rear и e входят во внутреннюю структуру класса Car. Такая организация позволяет задавать параметры для экземпляров классов Wheel и Engine в контексте класса Car, не изменяя классы wheels и engines в целом.

  • в контексте класса Car экземпляр в роли e можно подключить только к двум экземплярам в роли rear. Кроме того, экземпляры в ролях e и rear можно связать только в случае, если их роли относятся к одному и тому же экземпляру класса Car.

  • Другими словами, для экземпляров классов Wheel и Engine установлены дополнительные ограничения, когда они выступают в соответствующих ролях в рамках экземпляра класса Car. Эти ограничения не распространяются на классы Wheel и Engine в целом. Другие экземпляры классов wheels и engines могут быть привязаны произвольным образом, как показано на рис. (a).

Диаграмма, описанная в тексте.

Пример: роли компонентов в структурированном классе

Соединитель

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

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

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


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

Порт

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

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

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

Ниже приведены примеры портов:

Пример 1

Диаграмма, описанная в тексте.

Порт класса Engine, используемый классами Car и Boat

На рисунке выше показан класс Engine с портом p и двумя интерфейсами:

  • Предоставляемый интерфейс powertrain задает набор служб, которые класс предлагает через данный порт (т.е. допустимые операции и данные для порта).
  • Необходимый интерфейс power задает набор служб, предоставления которых класс ожидает от среды.

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

Для иллюстрации рассмотрим два примера использования класса Engine:

  • Класс Car соединяет порт p двигателя с набором колес через интерфейс axle.
  • Класс Boat соединяет порт p двигателя с винтом через интерфейс shaft.

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

Более того, если у класса Engine есть другие порты, например порт f (потребление топлива), колеса и винт по-прежнему будут обращаться к классу Engine через порт p. С портом f будет взаимодействовать указатель уровня топлива, независимо от того, какое топливо подается в двигатель и какие типы датчиков уровня топлива применяются в автомобилях и в лодках.

Пример 2

Данный пример основан на API протоколов Java ([JAV03]) - пакете, предоставляющем, среди прочих, следующие классы и интерфейсы для ведения протоколов на платформе Java 2.

  • Logger - основной объект, к которому будут обращаться приложения. Он применяется для занесения в протокол сообщений о конкретных компонентах приложения или системы.
  • Level - применяется для управления важностью и срочностью сообщений протокола.
  • Filter - применяется для тонкой настройки параметров занесения информации в протокол на более низком уровне, чем уровень протокола.
  • Handler - получает сообщения от Logger и экспортирует их в различных направлениях (в память, в потоки выходной информации, на консоли, в файлы и сокеты).
  • Formatter применяется для форматирования записей протокола.

Эти классы и интерфейсы участвуют в двух важных видах взаимодействий. Одни классы и интерфейсы применяются для занесения информации в протокол, а другие - для управления протоколами. На следующем рисунке проиллюстрирована разница во взаимодействии клиентов и администраторов с протоколом в модели UML:

  • Взаимодействие записи - объект в роли LogClient подключается к роли LogWriter для записи данных в протокол.
  • Взаимодействие администрирования - объект в роли LogAdministrator подключается к роли LogController для получения доступа к протоколу и изменения его параметров.

Диаграмма, описанная в тексте.

Виды взаимодействия клиентов и администраторов с протоколом

Одно из возможных представлений протокола и его служб в UML 2.0 - компонент с портами и объявленными интерфейсами, показанный на следующем рисунке:

Диаграмма, описанная в тексте.

Пакет Java Logging API, реализованный в виде компонента с набором интерфейсов, сгруппированных по портам

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

  • Интерфейсы Logger и Level сгруппированы в порт LogWriter. Клиенты служб протокола пользуются этими интерфейсами для записи данных в протокол.
  • Интерфейсы Handler, Filter и Formatter, объединенные в порт LogController. Данными интерфейсами администраторы пользуются для доступа к протоколу и изменения его параметров.

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

Моделирование

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

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

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

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

Диаграмма, описанная в тексте.

Пример: составная диаграмма структуры системы продажи билетов.

Представление UML 1.x

Учтите, что понятие структурированного класса появилось только в UML 2.0.

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

Если ваш инструментарий поддерживают только UML 1.5, можно воспользоваться альтернативным решением, описанным в разделах Рабочий продукт: Капсула и Рекомендации по рабочим продуктам: Капсула.

Дополнительные сведения приведены в разделе Различия между UML 1.x и UML 2.0.