Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Программная интерпретация свойств



Наиболее распространенным представлением свойства в программе является поле (С++, Java) или свойство языка (С#). Так, класс СтрокаЗаказа, показанный на рис. 4.9, мог бы быть представлен в C# следующим образом:

public class OrderLine

{ public int Quantity;

public Money Price;

public Order Order;

public Product Product;

}

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

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

public class OrderLine

{ …

private int quantity;

private Product product;

public int getQuantity() { return quantity; }

public void setQuantity ( int arg) { this. quantity = arg; }

public Money getPrice() { return product.getPrice().multiply(quantity); }

}

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

Если атрибут имеет несколько значений, то связанные с ним данные представляют собой коллекцию. Поэтому, объект Заказ (Order) будет ссылаться на коллекцию объектов СтрокаЗаказа (OrderLine). Поскольку эта кратность упорядочена ( ordered), то и коллекция должна быть упорядочена. В случае, если коллекция не упорядочена, то ее реализация происходит в виде множества, либо списка или массива. Так как UML подразумевает неограниченность сверху, рекомендуется для структур данных применять коллекцию.

Класс ассоциаций

Класс ассоциаций (Ассоциативный класс) – присоединяется к линии ассоциации пунктирной линией и рассматривается как класс со свойствами ассоциаций или как ассоциации со свойствами класса.

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

 

 

Рис. 4.12. Класс ассоциаций

Из данной диаграммы видно, что Личность может работать только в одной Компании. Для того, чтобы хранить информацию относительно периода работы служащего в Компании, нужно дополнить ассоциацию атрибутом «интервалВремени». Свойства класса-ассоциации характеризуют не один, а пару объектов, в данном случае – пару экземпляров классов Личность и Компания.

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

Рис. 4.13. Преобразование ассоциативного класса в обычный класс

 

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

Диаграмма на рис. 4.12 не допускает, чтобы Личность могла более одного раза работать в одной и той же Компании. Если все же в этом есть необходимость, то Работу следует преобразовать в обычный класс, как это сделано на рис. 4.13 (Личность может иметь более чем одну ассоциацию Работа с одной и той же Компанией).

На рис. 4.14 показан ассоциативный класс Оценка. Объект класса Оценка хранит список баллов, общий балл и оценку, полученную студентом) по предлагаемому курсу.

Рис. 4.14. Ассоциативный класс

 

Атрибут «списокбаллов» имеет параметризованный тип List (Number), где List определяет упорядоченное множество значений – список всех баллов, полученных студентом по данному курсу. То есть, если студент «Ахметов» проходит курс обучения по дисциплине «Информатика», со временем заполняется список (упорядоченное множество) баллов, полученных им в ходе обучения по этому курсу. Этот список баллов запоминается в объекте Оценка, который представляет собой ассоциацию между объектами «Ахметов» и «Информатика».

 

Операции класса

Как мы уже отмечали, объекты взаимодействуют с помощью отправки друг другу сообщений с помощью отношения ассоциации (по ассоциативной связи). Сообщение вызывает операцию целевого класса. Операция обслуживает запрос вызывающего объекта с помощью доступа к значениям атрибутов в своем собственном объекте. Чтобы подобный сценарий стал возможным, операции должны быть видимы (visible) внешним объектам (сообщения должны «увидеть» операции целевого класса). Говорят, что подобные операции обладают открытой видимостью ( public visibility).

В чисто объектно - ориентированной системе, большинство операций относятся к открытым, а большинство атрибутов – к закрытым. Значения атрибутов скрыты от других классов. Объекты одного класса (акторы) могут только затребовать услугу (операцию), опубликованную в открытом интерфейсе другого класса (сервер). Им не разрешается непосредственно манипулировать атрибутами другого объекта.

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

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

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

видимость Имя (список параметров): возвращаемый тип {характеристика}

· Метка видимости обозначает, относится ли операция к открытым (+) ( public ) или закрытым (-) ( private ), либо к пакетному (~) ( package ), либо к защищенному (#) ( protected ) уровням видимости.

· Список параметров – список параметров операции.

· Возвращаемый тип – тип возвращаемого значения, если таковое есть.

· Характеристика – значение свойства, которое применяется к данной операции.

Параметры операции имеют вид:

направление имя: тип = значение по умолчанию

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

· направление обозначает, является ли параметр входным ( in), выходным ( out ) или тем и другим ( inout ). Если направление не указано, то предполагается in. Например, в классе Счет операция может выглядеть так:

+balanceOn (data: Date): Money

 

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

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

Для операций определены следующие характеристики:

· leaf – операция, у которой нет потомков – не полиморфная операция;

· isQuery (запрос) – выполнение операции не изменяет состояние системы. Другими словами, операция является просто функцией без побочных эффектов;

· sequential (последовательная) – при вызове операции необходимо гарантировать, что в любой момент объект выполняет только один поток. При наличии нескольких потоков управления нельзя обеспечить семантику и целостность объекта;

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

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

Последние три характеристики ( sequential, guarded и concurrent ) описывают семантику параллелизма операции, поэтому задавать их имеет смысл только при наличии в модели активных объектов, процессов или нитей.

В языке UML существует различие между операцией и методом. Операциями называют услуги, которые можно запросить у любого объекта класса для изменения поведения; метод – это реализация операции. Для любой неабстрактной операции класса должен быть определен метод, содержащий ее исполняемый алгоритм.

Приведем некоторые допустимые объявления операций:

· Set ( in n: Name, out s: String) – имя и параметры

· GetID (): integer – имя и возвращаемое значение

· Restart() { guarded} – имя и характеристика

· +Display – видимость и имя

· Display – только имя

 

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

значений:

· in – входящий параметр, который не может быть модифицирован.

· out – выходной параметр, который может быть изменен, чтобы передать информацию вызвавшей процедуре;

· inout – входящий параметр, который может быть изменен.

 

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

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

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

Рассмотрим наиболее общепринятые стереотипы класса[4]:

· «actor» – определяет связанное множество ролей, которые играет пользователь варианта использования при взаимодействии с ним;

· «interface» – описывает множество операций, определяющих, что может делать класс и компонент;

· «type» – абстрактный класс, который используется только для спецификации структуры и поведения (но не реализации) множества объектов;

· «utility» – определяет класс, для которого область действия всех атрибутов и операций – класс;

· «implementationClass» – реализация класса на некотором языке программирования;

· «enumeration» – определяет перечислимый тип, включая его возможные значения, как набор идентификаторов;

· «exception» – определяет событие, которое может быть возбуждено или перехвачено операцией;

· «powertype» – классификатор, все объекты которого являются потомками данного родителя.

· «process» – классификатор, экземпляр которого представляет ресурсоемкий поток управления;

· «thread» – классификатор, экземпляр которого представляет облегченный поток управления;

· «boundary» – граничные классы, обеспечивают взаимодействие между окружающей средой и внутренними элементами системы. Такие классы предоставляют интерфейс для пользователя или другой системы (то есть, для актора). Они составляют внешне зависимую часть системы и используются для моделирования интерфейсов системы. Структура и поведение граничного класса определяются через призму «дружественности» системы к пользователю. Граничные классы также используются для обеспечения связи с другими системами. На этапе проектирования граничные классы совершенствуются и выносятся на обсуждение вопросов реализации протоколов взаимодействия.

· «entity»> – класс-сущность используется для моделирования данных и поведения с длинным жизненным циклом. Этот тип классов может представлять сущности реального мира или внутренние элементы системы. Такие классы обычно не зависят от окружения, то есть они нечувствительны к взаимодействию окружающей среды с системой. Следовательно, они не зависят от приложения и могут использоваться в различных приложениях. Классы-сущности – это обычно те классы, которые требуются системе для выполнения определенных обязанностей;

· «control» – управляющие классы, служат для моделирования последовательного поведения одного или нескольких вариантов использования и координации событий, реализующих заложенное в них поведение. Управляющие классы можно представить как классы, «исполняющие» вариант использования и определяющие его динамику, то есть они определяют поток основных и альтернативных событий в вариантах использования;

· «abstract» – важная концепция моделирования, которая логически вытекает из понятия наследования. Абстрактный класс – это родительский класс, который не имеет непосредственных объектов – экземпляров. Только подклассы абстрактного родительского класса могут быть материализованы как экземпляры.

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

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

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

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

В начале процесса разработки проекта устанавливаются преимущественно ассоциативные связи, с помощью которых проектируется структура проекта, далее, связи имеют тенденцию уточняться. Поэтому, после принятия тактических решений об истинных их отношениях, ассоциативные связи уточняются через отношения «наследование» (пара «обобщение - конкретизация»), «агрегация» (композиция) или «использование» (зависимость). При добавлении в проект интерфейсов, появляется отношение «реализация». На рис. 4.15 показаны значки отношений между классами.

 

Ассоциация

 

Агрегация

 

Композиция

Наследование

 

Зависимость

Реализация

 

Рис.4.15. Значки отношений между классами

Отношение «наследование»

Значок отношения «наследование», представляющего отношение “ is-a” («специализация/обобщение»), либо “ has-a” («включение»), выглядит как значок ассоциации с полой стрелкой на конце, которая указывает от Подкласса к Суперклассу (от наследника к родителю). В соответствии с правилами выбранного языка реализации, Подкласс наследует структуру и поведение своего Суперкласса. Конфликты имен между Суперклассами разрешаются в соответствии с правилами выбранного языка. К наследованию метка кратности не приписывается.

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

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

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

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

Класс – это подтип, если он может замещать свой супертип в независимости от того, использует он наследование (“is-a”), либо нет (“ has-a”). Создание Подкласса используется как синоним обычного наследования.

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

 

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

Зависимость является отношением использования между клиентом (зависимый исходный элемент) и сервером (независимый целевой элемент).

Зависимость – это семантическое отношение между двумя сущностями, при котором изменение одной из них может отразиться на семантике другой.

В случае отношений между классами, зависимости появляются по разным причинам [4]:

· один класс посылает сообщение другому классу (вызывает операцию поставщика);

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

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

Строгое отношение использования иногда несколько ограничительно, поскольку клиент имеет доступ только к открытой части интерфейса сервера.

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

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

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

На рис.4.16 [21] показаны базовые зависимости, которые можно обнаружить в многоуровневом приложении. Класс ОкноЛьгот – это пользовательский интерфейс, или класс представления, зависящий от класса Сотрудник. Класс Сотрудник – это объект предметной области, который представляет основное поведение системы, в данном случае – бизнес- правила. Это означает, что если класс Сотрудник изменяет свой интерфейс, то есть свое поведение, то, возможно, и класс ОкноЛьгот также должен измениться.

Рис.4.16. Пример базовой зависимости

 

Здесь важно то, что зависимость имеет только одно направление и идет от класса представления к классу предметной области. Таким образом, мы знаем, что имеем возможность свободно изменять класс ОкноЛьгот, не оказывая влияния на объект Сотрудник, или другие объекты предметной области. Здесь мы видим ценное правило анализа: «Строго разделять логику представления от логики предметной области, когда представление зависит от предметной области, но не наоборот».

Второй существенный момент этой диаграммы: здесь нет прямой зависимости классов ШлюзДанных от класса ОкноЛьгот. Если эти классы изменяются, то, возможно должен измениться и класс Сотрудник. Но если изменяется только реализация класса Сотрудник, а не его интерфейс, то на этом изменения и заканчиваются.

Рассмотрим другой пример зависимости, рис.4.17 [17].

 

Рис.4.17. Отношения зависимости

 

Рисунок показывает, что класс Заказ зависит от класса Книга, так как Книга используется в качестве типа параметров в операциях класса Заказ. Другая зависимость показывает, что класс ПросмотрЗаказа использует класс Заказ. Причем Заказ ничего не знает о классе ПросмотрЗаказа. Последняя зависимость помечена стереотипом « friend», который расширяет простую (базовую) зависимость.

Связь зависимость не является транзитивной. Например, как было показано на примере рис.4.16, если класс ОкноЛьгот зависит от класса Сотрудник и класс Сотрудник зависит от класса ШлюзДанных, тогда при изменении интерфейса класса ШлюзДанных может измениться реализация класса Сотрудник, но необязательно его интерфейс. Однако если зависимость является циклической (класс ОкноЛьгот зависит от класса Сотрудник, который зависит от ШлюзДанных, который, опять же, зависит от ОкноЛьгот), тогда изменения класса ШлюзДанных могут иметь циклический эффект, что делает процесс внесения изменений очень сложным и приводит к запутанному коду реализации.

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

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

 

Таблица 4.1


Поделиться:



Последнее изменение этой страницы: 2017-05-11; Просмотров: 329; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.254 с.)
Главная | Случайная страница | Обратная связь