GrandM-Patterns_in_Java
.pdf358 • Глава 8. |
Поведенческие шаблоны проектирования |
||
/ / Объединяет |
общие результаты . |
||
int [ ) |
myResult |
= new int [commonCount) ; |
|
commonCount = |
О ; |
|
|
for (int 1=0 , r=0 ; |
|
||
1<leftResu1t . 1ength && r<rightResu1t . 1ength ; ) { |
|||
if |
(leftResu1t[1) < rightResu1t [r) { |
||
|
1++; |
|
> rightResu1t [r) |
e1se if (leftResu1t[1) |
|||
|
r++; |
|
|
else |
|
|
|
|
myResu1t [commonCount) |
= 1eftResult[1) ; |
|
|
commonCount++ ; |
|
|
1++ ; |
|
|
|
r++ ; |
|
|
|
} |
/ / i f |
|
|
/ / |
for |
|
|
return myResu1t;
// contains ( String)
//class AndCombination
c1ass OrCombination extends Combination { private Combination 1eftChi1d, rightChi1d;
/ * * |
|
|
* |
Constructor |
|
* |
@pa ram |
left Левый потомок этого объекта . |
* |
@pa ram |
right Правый потомок этого объекта . |
* /
OrCombination=(Combination 1eft . Combination right) { 1eftChi1d =1eft;
rightChi1d right;
// con s tructor ( Combination, Combinat ion )
int [ ) |
contains (String з) { |
|
|||
int [ ) |
leftResu1t = |
1eftChi1d . contains (s) ; |
|||
int [ ) |
rightResu1t |
= |
rightChi1d . contains (s) ; |
||
if |
(leftResu1t == |
nul1) |
|
||
|
return rightResu1t; |
|
|||
if |
(rightResu1t == |
nu1l) |
О) |
||
|
return leftResult; |
||||
if |
(leftResult. length == |
Little Language • 359
return leftResult;
if (rightResult. length == О) return rightResult;
// Создает массив объединенных результатов . nt [] myResult
= new int [leftResult . length + rightResult . length] ; System . arraycopy (leftResult , О , myResult, О ,
leftResult . length) ;
System. arraycopy (rightResult, О , myResult, leftResult . length ,
rightResult . length) ; return myResult;
//contains ( S t ring)
// class OrCombination
ШАБЛОНЫ ПРОЕКТИРОВАНИЯ, СВЯЗАННЫЕ
С ШАБЛОНОМ LIПLЕ LANGUAGE
Composite. дерево синтаксического разбора организовано при помощи шаблона
Composite.
Visitor. Шаблон Visitor позволяет инкапсулировать в единственном классе ло гику выполнения несложных манипуляций с деревом синтаксического разбора.
Mediotor _ 361
Назначение этого диалогового окна состоит в том, чтобы предоставить необхо димую информацию ДЛЯ резервирования банкетного зала в отеле. Условия диа
л•огового окна соответствуют зависимостям между объектами диалога.
При первом появлении диалогового окна доступны только поля Number of People ( Количество человек) и кнопка отмены (Cancel). До тех пор пока в это поле не будет введено число в диапазоне от 25 до 1600, остальная часть диалога недоступна. После ввода количества человек становятся доступны ми поля Date (Дата) , Start Time (Время начала) и End Time (Время кониа), но они позволяют вводить только те значения времени, когда зал нужных размеров не занят. Доступны также кнопки-переключатели. Последующие изменения, вводимые в поле Number of People, делают доступными другие
•поля и кнопки -переключатели.
•Время начала должно быть раньше времени кониа.
Когда пользователь ввел данные в поля времени и даты и выбрал кнопку переключатель, появляется список блюд. Заказанные дата, время и вид об служивания определяют блюда, входящие в список. Некоторые блюда явля ются сезонными, и отель предлагает их только в течение некоторого перио
да времени года. Блюда для завтрака будут находиться в списке, предлагае
мом только для утренних банкетов. Некоторые блюда не годятся для
•шведских столов, а должны подаваться официантами.
Если выбрано хотя бы одноокблюдо. и текстовые поля содержат правильные данные, доступна кнопка
Если каждый объект диалогового окна отвечает за те зависимости , с которыми
он связан, в результате получится сильно связанный набор объектов, имеющих слабое сuепление (рис. 8.1 1).
Дли я упрощения этой диаграммы на ней не указаны имена ассоuиаuий, ролей
индикаторы множественности. Целью диаграммы является отображение всех
связей. Очевидно, что каждый объект участвует по крайней мере в двух зависи
мостях, а для некоторых объектов число зависимостей доходит до пяти. Боль
шая часть времени, затрачиваемого на реализаuию диалогового окна, пойдет на кодирование 15 связей зависимости.
Логика управления зависимостью распределена по восьми объектам, поэтому
рнадеализаuия диалогового окна сопряжена с немалыми трудностями. При работе диалоговым окном программист будет ВИдеть только небольшую часть Управления зависимостями. Ему будет сложно понять детали управления зави Симостями в uелом , и он не будет тратить на это время. Если программисты,
Поддерживая код, не имеют полного представления обо всех деталях, сопрово Ждение отнимает много времени, и часто его качество невысоко.
ОчевИдНО, что необходи ма реорганизаuия этих объектов, позволяющая сделать
вКОЛичество связей минимальным и объединить все управление зависимостями
одном сuепленном объекте. Такое усовершенствование экономит время про Граммиста и позволяет получить более надежный код. И менно для этой цели
Mediator - 363
МОТИВЫ
©Сушествует набор связанных объектов, и почти все объекты участвуют во
множестве отношений зависимостей.
©При определении подклассов предполагается участие отдельных объектов
в отношениях зависимости.
©Классы трудно использовать многократно, так как их функция усложнена отношениями зависимостей.
РЕШЕНИЕ
На диаграмме взаимодействия, представленной на рис. 8.1 3, показан обший
случай участия классов и интерфейсов в шаблоне Mediator.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
CoLLeaguel |
|
|
|
|
|
|
|
|
|
|
|
CoLLeague2 |
|
Е--- |
|||||||
|
|
|
addEventListenerl(:EventListenerl) |
|
|
addEventListen |
ег2(:ЕуеntListeпег2) |
|||||||||||||||||||||
|
1 |
. . . |
|
|
|
|
|
|
|
|
|
|
|
|
|
addEventListen |
егЗ(:ЕvепtListепегЗ) |
1 |
|
|||||||||
|
|
|
|
|
|
.....Извещает |
|
|
|
|
|
|
|
. . . |
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.....звещаеИ т |
|
||||||||
|
|
|
|
|
|
|
06 |
изменении |
|
|
|
|
|
.....звещИает |
|
|
|
|||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
06 |
изменении |
|
|
06 изменении |
|
|||||||||
|
|
|
|
|
lf |
состояния |
|
|
|
|
|
|
|
|
состояния |
|
lf |
состояния |
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
«interface» |
|
|
|
|
|
|
|
«interface» |
|
|
|||||||
|
|
|
|
«interface» |
|
I |
|
|
I |
|
|
I |
|
|
|
|
I |
I |
|
|||||||||
|
|
|
EventListenerl |
|
|
|
EventListener2 |
|
|
|
|
EventListener3 |
|
|||||||||||||||
|
|
|
|
|
t::I . |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||
|
|
|
|
|
I |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
I |
|
|
|
|||
|
|
|
|
|
- - - - - - - - - - - - - - - - - - - - - - - - , |
|
I ( - - - - - - - - - - - - - - - - - - - - - - - - |
|
|
|
||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
I |
|
I I |
|
|
|
|
|
|
|
|
|
|
|
|
|
....П |
|
т из |
менения |
|
|
|
|
|
|
Mediator |
|
|
|
|
|
|
|
Передает изменения ..... |
|||||||||
|
|
|
|
|
|
registerCoLLeaguel(ColLeaguel) |
|
|
|
|
||||||||||||||||||
|
ередае |
|
|
|
|
|
|
|
|
|
||||||||||||||||||
|
|
|
|
|
|
|
|
|
1 |
|
registerCoLLeague2(CoLLeague2) |
|
1 |
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
. . . |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
|
handLeEvent1( ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
handLeEvent2( ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
. .. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Рис. |
8.13. Классы шаблона Mediator |
|
|
|
|
|
|
|||||||||||
Опишем роли, исполняемые этими классами и интерфейсами. |
|
|
|
|||||||||||||||||||||||||
COlleag |
|
|
|
|
|
|
и т.д. |
Экземпляры классов в этой роли имеют зависимо |
||||||||||||||||||||
|
|
uel, Colleague2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
Сти, связанные с состояниями: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||
• |
один тип зависимости требует от объекта получить одобрение со стороны |
•других объектов на выполнение специальных изменений состояния;
другой ЧТОтип зависимости требует от объекта оповешения иных объектов
отом, он выполнил изменение состояния.
364 • Глава 8. Поведенческие шаблоны проектирования
Оба типа зависимостей обрабатываются похожим образом. Экземпляры клас
сов Col league l , Col league2 и т.д. связаны с объектом Mediator. Если ИМ
нужно оповестить другие объекты об изменении состояния, они вызывают ме
тод объекта Mediator. Метод иобъекта Mediator делает все остальное.
EventListenerl, EventListener2 Т.д. Интерфейсы в этой роли дают возмож ность классам Colleague l , Colleague2 и т.д. достичь высокой степени мно гократного использования, поскольку позволяют классам не знать, что они ра
ботают с объектом Mediator. Каждый из этих интерфейсов определяет методы,
связанные с событием определенного вида. Чтобы обеспечить извещения о со стоянии, объекты Colleague вызывают соответствующий метод нужного ин терфейса, ничего не зная о классе объекта Mediator, реализующем этот метод.
Mediator. Экземпляры классов в роли Mediator имеют логику для обработки
извещений о состоянии, полученных от объектов Col league l , Colleague2 И т.д. Классы Mediator реализуют один или несколько интерфейсов EventLis tener. Объекты Colleague l , Colleague2 вызывают методы, объявленные ИН терфейсами EventListener с целью проинформировать объект Mediator об из менении состояния. Затем объект Mediator выполняет соответствующую логику:
для извещений о предполагаемых измененияхдлясостояния логика обычно содер
жит одобрение или неодобрение изменения, извещений о выполненных из менениях состояа ния она обычно передает такие извещения другим объектам.
Классы Medi tor имеют методы, которые могут быть вызваны для их связи с объектами Col leaguel , Colleague2 и Т.д. Эти методы указаны на диаграмме как registerColleague l , registerColleague2 и Т.д. Они передаются соот ветствующему объекту Col league и обычно вызывают один или несколькоО его методов add . . . Listener с целью проинформировать объект Col league том, что он должен известить объект Mediator об изменении состояния.
Средства, предоставляемые объектами Col leaguel, Colleague2 и т.д. и по
зволяющие другим объектам выразить свою заинтересованность в изменении
состояния , и механизм передачи извещений о таких изменениях обычно согла суются с моделью делегирования событий в языке Java.
РЕАЛИЗАЦИЯ
Во многих случаях один объект отвечает за создание всех объектов Coll eague
и соответствующего объекта Mediator. Такой объект обычно выполняет роль
контейнера для создаваемых им объектов. Если существует единственный объ
ект, отвечающий за создание всех объектов Co lleague и их объекта Mediator.
то класс Mediator, как правило, объявляется как закрытый член этого класса.
Ограничивая видимость класса Mediator, повышают надежность программЫ.
При реализации шаблона Media tor нужно принять некоторые решения. ОднО из таких решений заключается в том, будет ли объект Media tor поддерживать
свою собственную внутреннюю модель состояния объектов Col league ИЛИ он
предпочтет считывать состояние каждого объекта всякий раз, когда потребуетсЯ
информация о состоянии объекта.
;66 • Глава 8. Поведенческие шаблоны лроектирования
Использование объекта Mediator обычно означает отсyrствие необходимо
сти создания подклассов классов Col league только для реализации управ
ления их зависимостями.
Классы Col league являются в большей степени многократно используе
мыми, так как на их основную функциональность не влияет код, управляю
ший зависимостями. Он обычно имеет тенденцию зависеть от приложения.
Размещение всей логики зависимостей набора связанных объектов в одном
месте упрощает понимание этой логики зависимостей. Если класс Mediator получается слишком большим, то разбиение его на мелкие части может
привестидля к тому, что он станет менее понятным.
Код управления зависимостями обычно зависит от приложения, поэтому классы Mediator, как правило, не являются многократно используемыми.
lРИМЕНЕНИЕ В JAVAAPI
Iримеры шаблона Mediator, которые можно найти в Java API, немного отлича )тся от тех посредников, которые, скорее всего, придется кодировать. Причи а в том, что код классов Mediator обычно зависит от приложения, а классы ava АР! от приложения не зависят.
jUI на основе языка Java может быть создан, главным образом, из объектов, оторые ЯRЛЯются экземплярами подклассов класса j ava . awt . swing . JComponent. )бъекты JComponent используют экземпляр подкласса класса j ava . awt . swing . ocusManager В качестве посредника. Если объекты JComponent связаны объектом FocusManager (а они обычно связаны), то они вызывают его метод roces sKeyEvent при получении KeyEvent. Задача объекта FocusManager со
гоит в том, чтобы распознать нажатия клавиш, которые должны активизировать
пределенный объект JComponent, что он и делает.
:пособ использования объектами JComponent объекта FocusManager отлича
гся от описанного в шаблоне Mediator ввиду следующих двух причин:
1. Объекты JComponent передают ключевые события от нажатия клавиШ
только объектам FocusManager . Большая часть классов Mediator, ко
торые придется писать, должны будyr управлять событиями несколькИХ
видов.
2. Объекты JComponent не обрашаются к объектам FocusManager через
интерфейс. Они прямо ссылаются на класс FocusManager. Если объек
ты JComponent ССЬUIаются на объекты FocusManager через интерфейс,
структура является более гибкой. Видимо, проектировщики Java АР!
посчитали здесь такую гибкость ненужной, поскольку взаимодействие
между объектами JComponent и объектами FocusManager осуществлЯ
ется на низком уровне.