Гради Буч - Объектно-ориентированный анализ и проектирование с примерами приложений на С++ (1158635), страница 42
Текст из файла (страница 42)
Имя каждого классадолжно быть уникально в содержащей его категории. Для некоторых языков, вособенности -Рис. 5-2. Значок классадля C++ и Smalltalk, мы должны требовать, чтобы каждый класс имел имя,уникальное в системе.На некоторых значках классов полезно перечислять несколькоатрибутов и операций класса. "На некоторых", потому что для большинстватривиальных классов это хлопотно и не нужно. Атрибуты и операции надиаграмме представляют прообраз полной спецификации класса, в которойобъявляются все его элементы. Если мы хотим увидеть на диаграмме большеатрибутов класса, мы можем увеличить значок; если мы совсем не хотим ихвидеть - мы удаляем разделяющую черту и пишем только имя класса.Как мы описывали в главе 3, атрибут обозначает часть составногообъекта, или агрегата.
Атрибуты используются в анализе и проектированиидля выражения отдельных свойств класса.2 Мы используем следующий независящий от языка синтаксис, в котором атрибут может обозначаться именемили классом, или и тем и другим, и, возможно, иметь значение по умолчанию:•Aтолько имя атрибута;только класс;•:C•A:C имя и класс;имя, класс и значение по умолчанию.•A:C=EИмя атрибута должно быть недвусмысленно в контексте класса. Вглаве 3 говорилось, что операция - это услуга, предоставляемая классом.Операции обычно изображаются внутри значка класса только своим именем.Чтобы отличать их от атрибутов, к их именам добавляются скобки.
Иногдаполезно указать полную сигнатуру операции:•N()только имя операции;класс возвращаемого значения (R), имя и•RN(Аргументы)формальныепараметры (если есть).Имена операций должны пониматься в контексте класса однозначно всоответствии с правилами перегрузки операций выбранного языка реализации.Общий принцип системы обозначений: синтаксис элементов, таких,как атрибуты и операции, может быть приспособлен к синтаксису выбранногоязыка программирования.
Например, на C++ мы можем объявить некоторыеатрибуты как статические, или некоторые операции как виртуальные иличисто виртуальные;3 в CLOS мы можем пометить операцию как метод:around. В любом случае мы пользуемся спецификой синтаксиса данногоязыка, чтобы обозначить детали. Как описывалось в главе 3, абстрактныйсвязь с методом Румбаха, мы оставляем его обозначения классов и объектов вкачестве допустимой альтернативы.2Точнее, атрибут эквивалентен отношению агрегации с физическим включением,метка которого совпадает с именем атрибута, а мощность равна в точности единице.3В C++ члены, общие для всех объектов класса, объявляются статическими',виртуальной называют полиморфную операцию; чисто виртуальной называютоперацию, за реализацию которой отвечает подкласс.класс - это класс, который не может иметь экземпляров.
Так как абстрактныеклассы очень важны для проектирования хорошей структуры классов, мывводим для них специальный значок треугольной формы с буквой А всередине, помещаемый внутрь значка класса (рис. 5-3). Общий принцип:украшения представляют вторичную информацию о некой сущности всистеме. Все подобные типы украшений имеют такой же вид вложенноготреугольника.Отношения между классами. Классы редко бывают изолированы;напротив, как объяснялось в главе 3, они вступают в отношения друг с другом.Виды отношений показаны на рис.
5-4: ассоциация, наследование, агрегация(has) и использование. При изображении конкретной связи ей можносопоставить текстовую пометку, документирующую имя этой связи илиподсказывающую ее роль. Имя связи не обязано быть глобальным, но должнобыть уникально в своем контексте.Значок ассоциации соединяет два класса и означает наличиесемантической связи между ними. Ассоциации часто отмечаютсясуществительными, например Employment (место работы), описывающимиприроду связи. Класс может иметь ассоциацию с самим собой (так называемаярефлексивная ассоциация).
Одна пара классов может иметь более однойассоциативной связи. Возле значка ассоциации вы можете указать еемощность (см. главу 3), используя синтаксис следующих примеров:•1В точности одна связьНеограниченное число (0 или больше)•N•0..N Ноль или больше•1..N Одна или большеРис. 5-3. Значок абстрактного классаРис. 5-4. Значки отношений между классами•0..1•3..7•1..3, 7Ноль или однаУказанный интервалУказанный интервал или точное числоОбозначение мощности пишется у конца линии ассоциации и означаетчисло связей между каждым экземпляром класса в начале линии сэкземплярами класса в ее конце. Если мощность явно не указана, топодразумевается, что она не определена.Обозначения оставшихся трех типов связи уточняют рисунокассоциации дополнительными пометками.
Это удобно, так как в процессеразработки проекта связи имеют тенденцию уточняться. Сначала мы заявляемо семантической связи между двумя классами, а потом, после принятиятактических решений об истинных их отношениях, уточняем эту связь какнаследование, агрегацию или использование.Значок наследования, представляющего отношение "общее/частное",выглядит как значок ассоциации со стрелкой, которая указывает от подклассак суперклассу. В соответствии с правилами выбранного языка реализации,подкласс наследует структуру и поведение своего суперкласса. Класс можетиметь один (одиночное наследование), или несколько (множественноенаследование) суперклассов. Конфликты имен между суперклассамиразрешаются в соответствии с правилами выбранного языка.
Как правило,циклы в наследовании запрещаются. К наследованию значок мощности неприписывается.Значок агрегации обозначает отношение "целое/часть" (связь "has") иполучается из значка ассоциации добавлением закрашенного кружка на конце,обозначающем агрегат. Экземпляры класса на другом конце стрелки будут вкаком-то смысле частями экземпляров класса-агрегата. Разрешаетсярефлексивная и циклическая агрегация. Агрегация не требует обязательногофизического включения части в целое.Знак использования обозначает отношение "клиент/сервер" иизображается как ассоциация с пустым кружком на конце, соответствующемклиенту.
Эта связь означает, что клиент нуждается в услугах сервера, то естьоперации класса-клиента вызывают операции класса-сервера или имеютсигнатуру, в которой возвращаемое значение или аргументы принадлежатклассу сервера.Пример. Описанные выше значки представляют важнейшие элементывсех диаграмм классов. В совокупности они дают разработчику наборобозначений, достаточный, чтобы описать фундамент структуры классовсистемы.Рис. 5-5 показывает, как описывается в этих обозначениях задачаобслуживания тепличной гидропонной системы.
Эта диаграмма представляеттолько малую часть структуры классов системы. Мы видим здесь классGardeningPlan (план выращивания), который имеет атрибут, названныйcrop (посев), одну операцию-модификаторРис. 5-5. Диаграмма классов гидропонной системыexecute (выполнить) и одну операцию-селектор canHarvest (можнособирать?). Имеется ассоциация между этим классом и классомEnvironmentalController (контроллер среды выращивания): экземплярыплана задают климат, который должны поддерживать экземплярыконтроллера.Эта диаграмма также показывает, что классEnvironmentalController является агрегатом: его экземпляры содержат вточности по одному экземпляру классов Heater (нагреватель) и Cooler(охлаждающее устройство), и любое число экземпляров класса Light(лампочка).
Оба класса Heater и Cooler являются подклассами абстрактногозапускающего процесс класса Actuator, который предоставляет протоколыstartUp и shutDown (начать и прекратить соответственно), и которыйиспользует класс Temperature.Существенное: категории классовКак объяснялось в главе 3, класс - необходимое, но недостаточноесредство декомпозиции. Когда система разрастается до дюжины классов,можно заметить группы классов, связанные внутри, и слабо зацепляющиеся сдругими. Мы называем такие группы категориями классов.Многие объектно-ориентированные языки не поддерживают этопонятие.
Следовательно, выделение обозначений для категорий классовпозволяет выразить важные архитектурные элементы, которые не могли бытьнепосредственно записаны на языке реализации.4Рис. 5-6. Значок категории классовКлассы и категории классов могут сосуществовать на однойдиаграмме. Верхние уровни логической архитектуры больших систем обычноописываются несколькими диаграммами, содержащими только категорииклассов.Категории классов. Категории классов служат для разбиениялогической модели системы. Категория классов - это агрегат, состоящий изклассов и других категорий классов, в том же смысле, в котором класс агрегат, состоящий из операций и других классов. Каждый класс системыдолжен "жить" в единственной категории или находиться на самом верхнемуровне системы. В отличие от класса, категория классов не имеет операцийили состояний в явном виде, они содержатся в ней неявно в описанияхагрегированных классов.На рис.
5-6 показан значок, обозначающий категорию классов. Как идля класса, для категории требуется имя, которое должно быть уникально вданной модели и отлично от имен классов.Иногда полезно на значке категории перечислить некоторые изсодержащихся в ней классов. "Некоторые", потому, что зачастую категориисодержат довольно много классов, и перечислять их все было бы хлопотно, даэто и не нужно.
Так же, как список атрибутов и операций на значке класса,список классов в значке категории представляет сокращенный вид ееспецификации. Если мы хотим видеть на значке категории больше классов,мы можем его увеличить. Можно удалить разделяющую черту и оставить взначке только имя категории.Категория классов представляет собой инкапсулированноепространство имен. По аналогии с квалификацией имен в C++, имя категорииможно использовать для однозначной квалификации имен содержащихся в4Среда программирования Smalltalk поддерживает концепцию категорий классов.Собственно это и подвигло нас на включение категорий в систему обозначений.Однако, в Smalltalk категории классов не имеют семантического содержания: онисуществуют только для более удобной организации библиотеки классов.
В C++категории классов связаны с концепцией компонент (Страуструп), они еще неявляются чертой языка, хотя включение в него семантики пространства именрассматривается [8]. (В настоящее время пространства имен включены в стандарт. Примеч. ред.)ней классов и категорий. Например, если дан класс A из категории B, то егополным именем будет A::B. Таким образом, как будет обсуждаться далее, длявложенных категорий квалификация имен простирается на произвольнуюглубину.Некоторые классы в категории могут быть открытыми, то естьэкспортироваться для использования за пределы категории.
Остальные классымогут быть частью реализации, то есть не использоваться никакими классами,внешними к этой категории. Для анализа и проектирования архитектуры эторазличие очень важно, так как позволяет разделить обязанности междуэкспортируемыми классами, которые берут на себя общение с клиентами, ивнутренними классами в категории, которые, собственно, выполняют работу.На самом деле, во время анализа закрытые аспекты категории классов можноопустить. По умолчанию все классы в категории определяются как открытые,если явно не указано противное.