Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
A01_Metaphor.doc
Скачиваний:
6
Добавлен:
12.11.2019
Размер:
762.37 Кб
Скачать

Контрольные вопросы

1) Сформулируйте своими словами понятие объект и приведите примеры объектов из различных прикладных областей.

2) Что является объектом с точки зрения восприятия человеком?

3) Что называется свойством объекта?

4) Что называется состоянием объекта?

5) Что называется поведением объекта?

6) Что называется ролью объекта?

5) Что называется ответственностью объекта?

7) Приведите пример(ы) объекта(ов), демонстрирующий(ие) понятия свойства, состояния, поведения, роли, ответственности объекта.

8) Сформулируйте понятие «идентичность объекта».

9) Какие операции называются методом, и какие – свободной подпрограммой?

10) Перечислите пять видов операций, и сформулируйте назначение каждого вида операций.

1.2. Отношения между объектами

1.2.1. Типы отношений. Сами по себе объекты не представляют никакого интереса: только в процессе взаимодействия объектов реализуется система. Мы получаем сообщество хорошо воспитанных объектов, которые вежливо просят друг друга об услугах. Самолет, по определению, «совокупность элементов, каждый из которых по своей природе стремится упасть на землю, но за счет совместных непрерывных усилий они преодолевают эту тенденцию». Самолет летит только благодаря согласованным действиям своих компонентов-объектов.

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

  • связи (взаимодействия);

  • агрегации.

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

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

Абстракция охлаждения имеет достаточно четкое поведение, что дает нам право на описание такого класса.

Опишем класс TTemperatureRamps (охлаждение), который по смыслу задает функцию времени от температуры:

class TTemperatureRamps

{

public:

TTemperatureRamps();

virtual ~ TTemperatureRamps ();

virtual void clear();

virtual void bind(float Temperature, int Minute);

virtual float temperatureAt(int Minute);

protected:

};

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

На самом деле в смысле поведения нам надо нечто большее, чем просто зависимость температуры от времени. Пусть, например, известно, что на 60-й минуте должна быть достигнута температура 150C, а на 180-й - 90C. Для ввода данных будем использовать функцию bind(). Теперь нам нужно узнать, какой должна быть температура на 120-й минуте? Это требует линейной интерполяции, так что требуемое от абстракции поведение усложняется. Для получения таких сведений введена функция temperatureAt().

Вместе с тем, управления нагревателем, поддерживающим требуемый режим остывания, мы от этой абстракции не требуем1. Мы предпочитаем разделение понятий, при котором нужное поведение достигается взаимодействием трех объектов: режима остывания (экземпляра класса TTemperatureRamps), нагревателя (экземпляра класса THeaters) и управляющего органа (экземпляра класса TRampControllers). Класс TRampControllers можно определить так:

class TRampControllers

{

public:

TRampControllers():

~ TRampControllers();

void process(TTemperatureRamps TemperatureRamp);

int schedule(TTemperatureRamps TemperatureRamp);

private:

};.

Операция process() обеспечивает основное поведение этой абстракции; ее назначение - передать график изменения температуры нагревателю, установленному в конкретном месте. Например, объявим:

TTemperatureRamps* objTemperatureRamp;

TRampControllers* objTRampController;.

Теперь, построив объекты, задав пару точек, определим режим остывания, загрузим его в контроллер и запустим процесс:

objTemperatureRamp -> bind(150, 60);

objTemperatureRamp -> bind(90, 180);

objTRampControllers -> process(objTemperatureRamp);.

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

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

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

Актер (Actor - это деятель, исполнитель; а исполнитель ролей, это и есть актер). Объект может воздействовать на другие объекты, но сам никогда не подвергается воздействию других объектов, это соответствует понятию «активный объект».

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

Агент. Такой объект может выступать как в активной, так и в пассивной роли; как правило, объект-агент создается для выполнения операций в интересах какого-либо объекта-актера или объекта-агента.

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

Видимость. Пусть есть два объекта А и B. Чтобы А cмог установить связь с объектом B, надо, чтобы B был в каком-то смысле видим для А. Мы можем не заботиться об этом на стадии анализа, но когда дело доходит до реализации системы, мы должны обеспечить видимость связанных объектов.

В предыдущем примере объект objTRampController видит объект objTemperatureRamp, поскольку оба они объявлены в одной области видимости и потому, что objTemperatureRamp передается объекту objTRampController в качестве параметра. В принципе есть следующие четыре способа обеспечить видимость:

  • сервер глобален по отношению к клиенту;

  • сервер (или указатель на него) передан клиенту в качестве параметра операции;

  • сервер является частью клиента;

  • сервер локально порождается клиентом в ходе выполнения какой-либо операции.

Какой именно из этих способов выбрать - зависит от тактики проектирования.

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

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

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

  • синхронный - функционирование пассивного объекта обеспечивается в присутствии многих потоков управления; взаимное исключение обеспечивает сам пассивный объект (сервер).

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

Printer -> Open(); ; Printer -> Close(); или

Clipboard -> Open(); ; Clipboard -> Close() или

GlobalLock(h); . . . ; GlobalUnLock(h).

В приведенных примерах Open(), GlobalLock(h) означают заблокировать объект от одновременного обращения других клиентов. Многоточием обозначено выполнение над объектом (принтером, буфером обмена, памятью) необходимых нашему приложению действий. Наконец, Close(),GlobalUnLock(h) осуществляют разблокирование коллективного ресурса, который становится доступным другим приложениям. Обратим внимание на неудачное использование понятий: Open (открывать) обозначает блокирование (закрытие) постороннего доступа, Close (закрывать) обозначает разблокирование (открытие) постороннего доступа. Использование термина Lock (запирать) надо признать более удачным

1.2.3. Отношение агрегации. В то время как связи обозначают равноправные или «клиент-серверные» отношения между объектами, агрегация определяет отношения целого и части, приводящие к соответствующей иерархии объектов, причем, идя от целого (агрегата), мы можем придти к его частям. В этом смысле агрегация - специализированный частный случай ассоциации. На рис. 1.1 объект objTRampController имеет два отношения: связь с объектом objTemperatureRamp и атрибут h класса THeaters (нагреватель). В данном случае objTRampController - целое, a h - его часть. Другими словами, h - часть состояния objTRampController. Исходя из objTRampController, можно найти соответствующий нагреватель. Однако по h нельзя найти содержащий его объект (называемый также его контейнером), если только сведения о нем не являются случайно частью состояния h.

 Агрегация

Рис. 1.1

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

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

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

h : THeaters;

каждый объект objRampController будет иметь свой нагреватель.

Замечание. Мы должны создавать нагреватель при создании нового контроллера, так как сам этот класс не предусматривает вызова конструктора нагревателя по умолчанию. Противоположный подход используется в потомках класса TComponent.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]