GrandM-Patterns_in_Java
.pdfГ Л А В А
Поведенческие
шаблоныпроектирования
Chain of RеsропsiЬШty (Цепочка ответственности) (31 1)
Command (Команда) (322)
Little Language (Малый язык) (333)
Mediator (Посредник) (360)
Snapshot (Моментальный снимок) (373)
Observer (Наблюдатель) (391)
State (Состояние) (401)
Null Object (Нулевой объект) (41 1 )
Strategy (Стратегия) (416)
Template Method (Метод шаблона) (422)
Visitor (Посетитель) (429)
Описанные в этой главе шаблоны используются для организации, управления
и объединения различных вариантов поведения.
Шаблон Chain of Responsibility позволяет объекту отправлять команду, ничего
Не зная об объекте или объектах, получающих ее. При этом команда передается цепочке объектов, которая обычно является частью более крупной структуры.
Каждый объект цепочки может обрабатывать, передавать команду следующему
Объекту цепочки или делать и то, и другое.
Шаблон Command инкапсулирует команды в объекте таким образом, что мож
Но управлять их выбором и послеДОВ<lтельностью, ставить их в очередь, отме
Нять их и выполнять иные манипуляции.
При помощи шаблона Little Language можно искать общие, создавать сложные
структуры данных и форматировать данные.
310 • Глава 8. Поведенческие шаблоны проектирования
Шаблон Mediator использует один объект для согласования изменения состоя ний других объектов. Вместо распределения логики по разным классам он поме
шает логику, предназначенную для управления изменением состояний других
объектов, в один класс. В результате получается более сцепленная реализация
логики и более низкая связанность этих классов.
Шаблон Snapshot записывает моментальный снимок состояния объекта таким
образом, чтобы это состояние можно было восстановить позднее.
Шаблон Observer позволяет объектам динамически регистрировать зависимо
сти между объектами. В результате объект будет оповещать зависящие от него
объекты об изменении своего состояния. ка
Шаблон State инкапсулирует состояния объекта в виде отдельных объектов,
ждый из которых расширяет общий суперкласс. Ш1Я
Шаблон NuU Object - альтернатива использованию null указания отсугствия
объекта, которому делегируется операция.
При помощи шаблона Strategy связанные алгоритмы инкапсулируются в клас сах, реализующих общий интерфейс. Это позволяет выбирать алгоритм путем определения соответствующего класса. Кроме того, этот шаблон позволяет из менять выбор алгоритма со временем.
Шаблон Template Method позволяет создать абстрактный класс, содержащий только часть логики, необходимой для выполнения задачи. Недостающая логи ка содержится в методах подклассов, которые замещают абстрактные методы.
Шаблон Visitor позволяет избежать усложнения классов объектов структуры, помещая всю необходимую логику в отдельный класс.
Этот шаблон ранее был описан в работе [GoF95].
с и н о п с и с
Шаблон Chain of ResponsibiIity позволяет объекту отправлять команду, ничего не зная об объекте или объектах, получающих ее. При этом команда передается цепочке объектов, которая обычно является частью более крупной структуры. Каждый объект цепочки может обрабатывать, передавать команду следующему объекту цепочки или делать и то, и другое.
КОНТЕКСТ
Предположим, создается программа, контролирующая систему безопасности. На физическом уровне система безопасности состоит из сенсорных устройств (детекторов движения, дыма и т.д.), которые передают информацию о состоя нии компьютеру. Задача компьютера состоит в том, чтобы записывать всю ин формацию о состояниях, отображать текущую информацию о состоянии и пе редавать сигналы тревоги в случае аварии.
Контролирующая программа должна обеспечивать высокую степень масштаби руемости, т.е. работать в маленьких розничных магазинчиках, офисных зданиях,
больших складских помещениях или в комплексах, состоящих из нескольких
зподани. й. Это требование влияет на способ проектирования контролирующего
ЧТОбы не быть слишком сложной, контролирующая программа должна инстан
циировать объектдля каждого сенсорного устройства. Тогда способ моделирова ния состояния каждого сенсора будет простым. Чтобы обеспечить масштаби
руемость,
о объекты, отвечающие за отдельные сенсоры, не должны ничего знать
своем окружении, за исключением того, что они находятся на самом нижнем
уРовне иерархической схемы.
Схема будет содержать объекты, соответствующие таким реально существую
щим вещам, как комнаты, площадки, этажи и здания. Прямое моделирование
Реального мира - это простой способ отображения состояния различных час Тей здания. Кроме того, он позволяет интерпретировать состояние сенсоров, ИсходЯ из окружающей их среды. Например, если температура в закрытом по Мещении превышает 85", нужно включить противопожарные разбрызгиватели
ТОЛько в этой комнате. Если температура на открытой площадке склада превы
СИТ 65", то можно включить противопожарные разбрызгиватели по всей этой
ПЛощади и на соседних площадках. С другой стороны, если температура
312• Глава 8. Поведенческие wаблоны проектирования
вморозильнике превышает -4", можно включить звуковой сигнал тревоги, ко
торый даст знать, что морозильник слишком теплый.
Во всех этих случаях объект, моделирующий сенсор, сам не решает, что делать
с состоянием сенсора. Вместо этого он делегирует принятие решения объекту,
находящемуся на более высоком уровне иерархии и обладающему большей ин формацией о контексте. Такие объекты либо решают, что делать с извещением,
либо передают его объекту, стоящему на более высоком уровне иерархии.
На рис. 8 . 1 показан пример иерархической организации объектов.
:Building
Рис. 8.1. Объекты физической безопасности
Например, если объект TemperatureSensor, находящийся на территориит склада, получает от физического сенсора извещение о текущей температуре, о
он передает это извещение содержащему его объекту Area. Вместо принятия
решения по поводу критичности температуры Area передает извещение содер жащему его объекту Warehouse. Объект Warehouse оценивает температурУ.
Если она превышает 65", объект Warehouse принимает решение, что возник
пожар. Он включает разбрызгиватели в той области, которая его оповестила,
и в близлежащих областях. Объект Warehous e не передает извещения о темпе
ратуре.
моти в ы
© Нужно, чтобы объект мог посылать кома ду другому объекту, не идентифИ
н т об
цируя получателя. Объекта-отправителя беспокоит не то, какой объек ко работает команду, а только то, что некоторый объект должен получить манду и обработать ее.
© Необходимо, чтобы получатели команды имели возможность обрабатыватЬ
команду, ничего не зная об объекте, который ее послал.
Chain of Responsibility - 313
©Получать и обрабатывать команду могуг несколько объектов, поэтому ну
жен способ задания приоритетов получателей, не загружая объект-отправи тель сведениями об этих получателях.
©Объекты, способные обрабатывать команды, организованы в виде структу
ры, которая может использоваться для задания приоритетов потенциальных обработчиков команд.
РЕШЕНИЕ
На рис. 8.2 представлена диаграмма классов, описывающая организацию шаб лонав Chain ofResponsibility. Опищем роли, исполняемые классами и интерфейсом
этом щаблоне.
CommandSender. Экземпляры класса, выступающего в роли CommandSender,
отправляют команды первому объекту цепочки объектов, способных обрабо
тать команду. Он посылает команду, вызывая метод postCommand первого объ
екта CommandHandlerIF.
CommandHandlerIF. Все объекты цепочки, имеющие возможность обрабатывать команду, должны реализовывать интерфейс, выступающий в этой роли. Он оп ределяет два метода:
1. Метод handleCommand для обработки любых команд, которые должны об
рабатываться реализующим классом. Метод handleCommand возвращает true, если он обработал команду, или false, если не обработал.
2.Метод postCommand, который вызывает метод handleCommand. Если метод handleCommand возвращает false и в цепочке имеется следующий объект, он вызывает метод postCommand этого объекта. Если метод handleCommand возвращает true, это значит, что не нужно передавать команду следующему объекту цепочки.
AbstractCommandHandler. Классы, играющие эту роль, являются абстрактными классами, реализующими метод pos tCommand. Это позволяет воспользоваться преимуществами общей реализации метода postCommand в классах, высту куПающих в роли ConcreteCommandHandler. Обычно классы используют логи по умолчанию для метода postCommand. Классы, выступающие в роли
ComтandSender, должны ссылаться на объекты цепочки ответственности не
как на экземпляры класса AbstractCommandHandler, а только- через интер
фейс CommandHandlerIF. Класс AbstractCommandHandler это просто де
iаль реализации. Хотя это и не обычная практика, классы могуг реализовывать
Интерфейс CommandHandlerIF и не ЯWIЯться подклассами класса AbstractCom
lI\andHandler. |
и Т.Д. Экземпляры клас |
ConcreteCommandHandlerl, ConcreteCommandHandler2 |
сов в этой роли представляют собой объекты цепочки ответственности, кото
РЫе могуг обрабатывать команды.
Как правило, объекты CommandHandler являются частью более крупной струк-
1'уры (рис. 8.2).
Chain of Responsibility - 315
СЛЕДСТВИЯ
©Шаблон Chain of Responsibility уменьшает связанность между объектом, от правляющим команду, и объектом, обрабатываюшим комаНдУ. Отправитель комаНдЫ не должен знать о том, какой объект реально обработает команду. Он просто должен иметь возможность отправить комаНдУ объекту, находя щемуся в начале uепочки ответственности.
©Шаблон Chain ofResponsibility допускает гибкость во время принятия реше ния, каким образом обрабатывать комаНдЫ. Решение о том, какой объект будет обрабатывать команду, может меняться при изменении объектов, вхо дящих в uепочку ответственности, или при изменении последовательности
• |
объектов в uепочке ответственности. |
Шаблон Chain of Responsibility не гарантирует обработку каждой комаНдЫ. |
|
|
Необработанные комаНдЫ игнорируются. |
®Если количество объектов в uепочке слишком велико, то могут быть про блемы с эффективностью, касающиеся времени, необходимогодля прохож дения комаНдЫ по uепочке. Высокий проuент необработанных комаНд усу губляет проблему, так как необработанные комаНдЫ проходят по всей дли не uепочки.
Модель делегирования событий
Модель делегирования событий предусматривает использование объек тов• трех видов:
источники событий представляют собой объекты, которые являются
•источниками информаuии о возникновении события некоторого вида;
приемники событий представляют собой объекты, которые должны
•знать о появлении события некоторого определенного вида;
события - это объекты, которые инкапсулируют информаuию о по-
явлении события.
Объекты-источники событий передают объекты-события объектам-при емникам событий. Объекты событий являются экземплярами подкласса
класса j ava . u t i l . EventObj ect.
Существует соглашение об именах, которое задает структуру модели де легирования событий. Проиллюстрируем это соглашение при помощи событий действий.
События Action представляются классом ActionEvent. Чтобы экземп ляры некоторого класса могли получать события действий, этот класс должен реализовывать интерфейс ActionListener. Такие интерфейсы,
Choin of Responsibility 8 317
которых приложений передача команды объекту вне цепочки обработчиков почти
всегда вызывает ошибку. Пример системы физической безопасности, рассмот реннЫЙ в разделе «(Контекст.), представляет собой пример такого приложения.
Для приложений такого рода использование шаблона Chain ofResponsibility по зволяетделать меньше ошибок, чем применение модели делегирования события.
льюЕше одно преимушество шаблона Chain of ResponsibiIity по сравнению с моде делегирования событий состоит в том, что он позволяет явным образом
контролировать порядок передачи событий обработчикам.
ПРИМЕР КОДА
На рис. 8.3 представлены классы, используемые в примере системы физиче ской безопасности.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SecurityZoneIF |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
notify(measurement:int, source:Sensor) |
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fireAlarm(zone:SecurityZone) |
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sensor |
|
|
|
|
|
|
|
Abstract5ecurityZone |
|||
|
|
|
|
|
|
|
|
|
|
|
|
notify(measurement:int) |
|
|
|
|
|
notify(measurement:int, source:Sensor) |
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hand/eNotification(measurement:int. |
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
... |
source:sensor):boo/ean |
|||
|
|
|
|
|
|
|
|
I |
|
I MotionSensor |
I |
|
|
|
. .I |
|
fireAlarm(zone:SecurityZone) |
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
. |
I |
|
|
|
||||||||
|
|
TemperatureSensor |
|
|
|
|
|
|
I |
|
|
|||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
Building |
|
|
|
|
|
|
|
|
|
Warehouse |
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hand[еNotificatiоп(measurement:int, |
|||
|
|
handleNotification(measurement:int, |
|
|
|
|
|
|
|
|||||||||||||||
|
|
|
|
|
|
|
|
|
|
source:Sensor):boolean |
|
|
|
|
|
|
|
source:Sensor):boolean |
||||||
|
|
|
|
|
|
|
|
|
|
|
I |
|
|
|
|
|
|
|
|
|
I |
|||
|
|
|
|
|
|
|
|
|
|
Floor |
|
|
|
|
|
|
|
|
|
Агеа |
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
handleNotificatiоп(measurement:int, |
|||||||||||
|
|
handleNotification(measuгетent:int, |
|
|
|
|
|
|
|
|||||||||||||||
|
|
.... |
|
|
|
|
source:Sensor):boolean |
|
|
|
|
|
|
|
source:Sensor):boolean |
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||
.... |
|
|
|
|
|
I |
|
|
|
|
|
|
|
|
|
|
|
|
||||||
t- |
|
|
|
Room |
|
|
|
|
|
|
|
|
|
Freezer |
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||
|
|
handleNotificatiоn(measurement:int, |
|
|
. . . |
|
|
|
|
|
||||||||||||||
|
|
|
|
|
|
handleNotification(measurement:int, |
|
|||||||||||||||||
.... |
|
|
|
|
source:Sensor):boolean |
|
|
|
|
|
|
|
source:Sensor):boolean |
|
||||||||||
|
|
|
|
|
|
|
|
|
|
Рис. 8.3. |
Классы системы физической безопасности |