Главная страница / 30. Объектно-ориентированные методы анал...: 30.4. Основные элементы о...

30.4. Основные элементы объектной модели

К основным понятиям объектно-ориентированного подхода (элементам объектной модели) [18] относятся:

  • объект;
  • класс;
  • атрибут;
  • операция;
  • полиморфизм (интерфейс);
  • компонент;
  • связи.
Объект определяется как осязаемая сущность (tangible entity) – предмет или явление (процесс), имеющая четко определяемое поведение.

Объект может представлять собой абстракцию некоторой сущности предметной области (объект реального мира) или программной системы (архитектурный объект). Любой объект обладает состоянием (state), поведением (behavior) и индивидуальностью (identity).

Состояние объекта – одно из возможных условий, в которых он может существовать, оно изменяется со временем.

Состояние объекта характеризуется перечнем всех возможных (статических) свойств данного объекта и текущими значениями (динамическими) каждого из этих свойств. Состояние объекта определяется значениями его свойств (атрибутов) и связями с другими объектами.

Поведение определяет действия объекта и его реакцию на запросы от других объектов.

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

Каждый объект обладает уникальной индивидуальностью.

Индивидуальность – это свойства объекта, отличающие его от всех других объектов.

Структура и поведение схожих объектов определяют общий для них класс. Термины «экземпляр класса» и «объект» эквивалентны.

Графическое представление объекта как экземпляра класса в языке моделирования UML [28] показано на рис. 30.1.


Рис. 30.1. Графическое представление объекта как экземпляра класса

Класс – это множество объектов, связанных общностью свойств, поведения, связей и семантики.

Класс инкапсулирует (объединяет) в себе данные (атрибуты) и поведение (операции). Класс является абстрактным определением объекта и служит в качестве шаблона для создания объектов. Графическое представление класса в языке UML показано на рис. 30.2. Класс изображается в виде прямоугольника, разделенного на три части. В первой содержится имя класса, во второй – его атрибуты, в третьей – операции класса, отражающие его поведение (действия, выполняемые классом). Ниже приведён пример класса TFrac (простая дробь) на языке Object Pascal. С помощью этого класса реализованы простые дроби. Объектом этого класса является простая дробь.

TFrac = class//Простая дробь
public
    constructor Create(n: integer = 0;d: integer = 1);//конструктор
    function Add(b: TFrac): TFrac;//Сложение простых дробей
    function Sub(b: TFrac): TFrac;//Вычитание простых дробей
    function Mul(b: TFrac): TFrac;//Умножение простых дробей
    function Dvd(b: TFrac): TFrac;//Деление простых дробей
    function ToStrint(): string;//Преобразование дроби в строку
private
    FNum: integer;//Числитель
    FDen: integer;//Знаменатель
end;

Любой объект является экземпляром (instance) класса. Определение классов и объектов – одна из самых сложных задач объектно-ориентированного проектирования.

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

Атрибут – это элемент информации, связанный с классом. Например, у класса Company (Компания) могут быть атрибуты Name (Название), Address (Адрес) и NumberOfEmployees (Число служащих).


Рис. 30.2. Графическое представление класса

Так как атрибуты содержатся внутри класса, они скрыты от других классов. В связи с этим может понадобиться указать, какие классы имеют право читать и изменять атрибуты. Это свойство называется видимостью атрибута (attribute visibility).

У атрибута можно определить три возможных значения видимости. Рассмотрим каждое из них в контексте примера (рис. 30.2). Пусть имеются класс Employee с атрибутом Address и класс Company:

Public (общий, открытый). Это значение видимости предполагает, что атрибут будет виден всеми остальными классами. Любой класс может просмотреть или изменить значение атрибута. В таком случае класс Company может изменить значение атрибута Address класса Employee. В соответствии с нотацией UML общему атрибуту предшествует знак «+».

Private (закрытый, секретный). Атрибут, обладающий этим значением видимости, не виден никаким другим классом. Класс Employee будет знать значение атрибута Address и сможет изменять его, но класс Company не сможет его ни увидеть, ни редактировать. Если это понадобится, он должен попросить класс Employee просмотреть или изменить значение этого атрибута, что обычно делается с помощью общих операций. Закрытый атрибут обозначается знаком «-» в соответствии с нотацией UML.

Protected (защищенный). Атрибут, обладающий таким значением видимости, доступен только самому классу и его потомкам в иерархии наследования.

Допустим, имеется два различных типа сотрудников – с почасовой оплатой и на окладе. Таким образом, потомками класса Employee будут два класса – HourlyEmp и SalariedEmp. Защищенный атрибут Address можно просмотреть или изменить из классов Employee, HourlyEmp и SalariedEmp, но не из класса Company. Нотация UML для защищенного атрибута – это знак «#».

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

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

Операции отражают поведение объекта. Операция-запрос не изменяет состояния объекта. Операция-команда может изменить состояние объекта. Результат операции зависит от текущего состояния объекта.

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

Операции реализуют связанное с классом поведение (иначе говоря, реализуют обязанности класса — responsibilities). В широком смысле обязанности класса делятся на две категории.

Знание (определяется атрибутами класса):

  • наличие информации о данных или вычисляемых величинах;
  • наличие информации о связанных объектах.

Действие (определяется операциями класса):

  • выполнение некоторых действий самим объектом;
  • инициация действий других объектов;
  • координация действий других объектов.

Операция включает три части – имя, параметры и тип возвращаемого значения. Параметры – это аргументы, получаемые операцией «на входе». Тип возвращаемого значения относится к результату действия операции.

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

Имя Операции (аргумент1: тип данных аргумента1, аргумент2: тип данных аргумента2,...): тип возвращаемого значения

Существуют четыре различных типа операций.

  • Операции реализации (implementor operations) реализуют некоторые функции (процедуры). Такие операции выявляются путем анализа диаграмм взаимодействия UML.
  • Операции управления (manager operations) управляют созданием и уничтожением объектов. В эту категорию попадают конструкторы и деструкторы классов.
  • Атрибуты обычно бывают закрытыми или защищенными. Тем не менее, другие классы иногда должны просматривать или изменять их значения. Для этого существуют операции доступа (access operations).
  • Вспомогательными (helper operations) называются такие операции класса, которые необходимы ему для выполнения его обязанностей, но о которых другие классы не должны ничего знать. Это закрытые и защищенные операции класса.

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

Полиморфизм – это способность скрывать множество различных реализаций под единственным общим интерфейсом.

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

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

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

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

Компонент представляет собой физическую реализацию проектной абстракции и может быть:

  • компонентом исходного кода;
  • компонентом времени выполнения (run time);
  • исполняемым компонентом.

Компонент обеспечивает физическую реализацию набора интерфейсов.

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

Ассоциация (association) – это семантическая связь между классами.

Ее изображают на диаграмме классов в виде обыкновенной линии (рис. 30.3). Ассоциация отражает структурные связи между объектами различных классов.


Рис. 30.3. Ассоциация

Агрегация (aggregation) представляет собой форму ассоциации – более сильный тип связи между целым (составным) объектом и его частями (компонентными объектами).

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

Слабая форма агрегации в UML называется просто агрегацией. При этом составной объект физически не содержит компонентный объект. Один компонентный объект может обладать несколькими связями ассоциации или агрегации.

Агрегация изображается линией между классами с ромбом на стороне целого объекта (рис. 30.4). Сплошной ромб представляет композицию (рис. 30.5).


Рис. 30.4. Агрегация


Рис. 30.5. Композиция

Мощность (multiplicity) показывает, как много объектов участвует в связи.

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

В языке UML приняты следующие нотации для обозначения мощности.

Значение мощности
Мощность Значение
* Много
0 Нуль
1 Один
0..* Нуль или больше
1..* Один или больше
0..1 Нуль или один
1..1 Ровно один

Например, при разработке системы регистрации курсов в университете можно определить классы Course (учебный курс) и Student (студент). Между ними установлена связь, означающая посещение курсов студентами. Если один студент может посещать от нуля до четырех курсов, а на одном курсе могут заниматься от 10 до 20 студентов, то на диаграмме классов это можно изобразить следующим образом (рис. 30.6).


Рис. 30.6. Мощность связи

Зависимость (dependency) – связь между двумя элементами модели, при которой изменения в спецификации одного элемента могут повлечь за собой изменения в другом элементе.

Зависимость – слабая форма связи между клиентом и сервером (клиент зависит от сервера и не имеет знаний о сервере). Зависимость изображается штриховой линией, направленной от клиента к серверу (рис. 30.7).


Рис. 30.7. Зависимость

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

Обобщение (generalization) – связь «тип-подтип» реализует механизм наследования (inheritance). Большинство объектно-ориентированных языков непосредственно поддерживает концепцию наследования. Она позволяет одному классу наследовать все атрибуты, операции и связи другого.

В языке UML связи наследования называют обобщениями и изображают в виде стрелок от класса-потомка к классу-предку (рис. 30.8).


Рис. 30.8. Обобщение

Общие атрибуты, операции и/или связи отображаются на верхнем уровне иерархии.

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