![](/user_photo/2706_HbeT2.jpg)
GrandM-Patterns_in_Java
.pdf![](/html/2706/346/html_MxkKzTLKJz.Ja4Q/htmlconvd-LkZgZ6421x1.jpg)
428• Глава 8. Поведенческие шаблоны проектироваНИR
* @param authToken
* Этот объект возвращает метод аутентификации .
* / abstract
protected void notifyAuthentication (Object authToken)
// class Abs t ractLogon
Подклассы класса A b s t ractLogon должны замещать абстрактные методы это го класса примерно таким образом:
public class Logon extends AЬstractLogon
protected Object authenticate (String userID , String password)
throws Exception
if (userID . equals ("abc") && password . equals ("123"» return userID ;
throw new Exception ("bad userID") ;
/ / authent icate
protected void notifyAuthentication (Object authToken) (
// noti fy (Obj ect)
// class Logon
ШАБЛОН ПРОЕКТИРОВАНИЯ, СВЯЗАННЫЙ С ШАБЛОНОМ TEMPLATE METHOD
Strategy. Шаблон Strategy изменяет логику отдельных объектов на стадии вы
полнения. Шаблон Template Method изменяет логику всего класса на стадии
компиляции.
![](/html/2706/346/html_MxkKzTLKJz.Ja4Q/htmlconvd-LkZgZ6423x1.jpg)
430 • Глава 8. Поведенческие шаблоны проектирования
Поскольку такие операции предполагают манипулирование документом тек
стового процессора, любой проект, реализующий характеристики оглавления,
должен будет содержать классы, используемые текстовым процессором для
представления документов (рис. 8.31).
|
|
|
|
|
|
l' |
О..* |
|
|
|
|
||||||
|
|
|
«interface» |
|
|
|
|
|
|||||||||
|
|
|
DocumentElementIF |
|
|
|
|
|
|
|
|
||||||
|
|
getStyle. .. |
|
I!& |
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
I |
|
|
|
|
|
|
|
|
|
|
||
_-------- - - - - - - - - - - -- - - - - ----------- - - - - , |
1 1 |
1 |
|
|
|||||||||||||
I |
|
|
|
|
|
|
|
I |
|
|
|
|
|||||
I |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DocChar |
|
|
|
|
|
|
|
CompositeOocumentElement |
|
|
|
|
|||||
|
|
|
|
|
|
getChild(index:int) : DocumentElement |
|
|
|
||||||||
|
|
|
|
|
|
addChild(child:DocumentElement) |
|
|
|
|
|||||||
|
|
|
|
|
|
removeChild(child:DocumentElement) |
|
|
|
|
|||||||
|
|
|
|
|
. . . |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
Document |
|
|
|
|
Paragraph |
|
|
|
LineOfТext |
|||||
|
|
|
|
Рис. 8.31. |
Классы документа |
|
|
|
|
С точки зрения механизма оглавления интерес представляют следующие клас сы: Document, Paragraph и LineOfText. Документ содержит абзацы, которые включают строки текста. Любой проект, предполагающий создание оглавле ния, должен учитывать то, что объекты Document могуг содержать объекты, не являющиеся объектами Paragraph. Кроме того, необходимо принимать во
внимание, что содержать объекты Paragraph могуг не только объекты Docu ment, но И другие виды объектов. И наконец, проект не должен усложнять
классы, представляющие документы.
При реализации характеристик оглавления нужно рассмотреть два основныХ
подхода. Один предусматривает размещение необходимой логики в различных
классах, представляющих документ. Исходя из соображений, рассмотренных
в разделе « Синопсис», это не лучшее решение.
Другой подход предполагает размещение всей логики, связанной с какой-тО
операцией, в одном классе. По завершении связанной с оглавлением операциИ
объект, отвечающий за операцию, просматривает объект Document И содержа
щиеся в нем объекты. Он ищет объекты Paragraph, которые содержатся не
посредственно в объекте Document. Когда он находит объекты Paragraph со
стилем , который хранится во внутренней таблице оглавления , управляющей
связанной с оглавлением операцией, он предпринимает необходимые действИЯ
(рис. 8.32). Структура, показанная на рис. 8.32, использует также классы, изо
браженные на рис. 8.31.
![](/html/2706/346/html_MxkKzTLKJz.Ja4Q/htmlconvd-LkZgZ6424x1.jpg)
432 • Глава 8. Поведенческие шаблоны проектирования
ветствующий элемент оглавления. Элемент оглавления использует содеРЖИМое
первогО объекта LineOfText, принадлежащего объекту Paragraph.
ReorgVisitor. Этот подкласс класса DocumentVi s i tor отвечает за автомаТИче
ское разделение документа на несколько файлов. Сначала ему сообщают, что бы он осуществил поиск абзацев, соответствующих определенному УРОВню
структуры документа. Он находит этот уровень структуры во внутренней табли
це оглавления и считывает из нее стиль, связанный с этим уровнем структуры.
Затем он просматривает все объекты Paragraph, принадлежащие объекту
Document. Он ищет те объекты Paragraph, которые имеют стиль, прочитан
ный им из таблицы. Когда ReorgVis i tor находит объект Paragraph с нужным
стилем, он создает новый объект Document, перемещает найденный объект
Paragraph вместе со всеми объектами Paragraph, непосредственно следую
щими за ним и находящимися на более низком уровне структуры, во вновь соз данный объект Document. Класс ReorgVi s i tor записывает в файл новый объ ект Document И все объекты абзацев, связанные теперь с ним. Он заменяет
объекты Paragraph, которые он переместил из исходного объекта Document, новым объектом, содержащим имя файла, в котором теперь хранятся переме щенные абзацы.
МОТИВЫ
©Имеются различные операции, которые должны выполняться для некото рой структуры объектов.
©Структуру образуют объекты, принадлежащие разным классам.
©Типы объектов структуры меняются не часто, а их объединения являются
согласованными и предсказуемыми.
РЕШЕНИЕ
в этом разделе рассматриваются две версии шаблона Visitor. Первая представ
ляет идеальное решение, дающее идеальный результат. К сожалению, во мно гих ситуациях идеальное решение не будет работать или будет работать неэф
фективно. Вторая версия шаблона Visitor применима для множества разных
ситуаций, но связана с издержками из-за ввода дополнительных зависимоСтей
между классами.
На рис. 8.33 представлена диаграмма классов, демонстрирующая роли, испоЛ
няемые классами в идеальной версии шаблона Visitor.
Опишем роли, исполняемые такими классами.
Client. Экземпляры классов в этой роли предназначены для манипулированиЯ всей структурой объектов и объектами, входяшими в состав этой структурЫ.
С целью выполнения вычислений для структур объектов, за которые они отве
чают, они используют объекты ConcreteVis itor.
![](/html/2706/346/html_MxkKzTLKJz.Ja4Q/htmlconvd-LkZgZ6426x1.jpg)
![](/html/2706/346/html_MxkKzTLKJz.Ja4Q/htmlconvd-LkZgZ6427x1.jpg)
434 • Глава 8. Поведенческие шаблоны проектирования
всвои вычисления объект ConcreteElement. По окончании операции объект
ConcreteEl ement передает объект AbstractVi s itor методу accept ДРУГОго
объекта ConcreteElement.
Visitor. Выстудля пающий в этой роли класс представляет собой абстрактный су перкласс классов, выплняющихдля x вычисления над элементами структуры
объектов. Он определяет метод каждого класса, который будут «посещатЪ» его подклассы, поэтому их экземпляры могут передавать сами себя объектам
Vis i tor и принимать участие в вычисленияхи Т.д. .
ConcreteVisitorl, ConcreteVisitor2 Экземпляры классов, выступающих
в этой роли, образуют структуру объектов.
На рис. 8.34 представлена диаграмма взаимодействия, более очевИдНО демонст
рирующая то, как объекты Vis i tor сотрудничают с объектными структурами.
На этом рисунке показано взаимодействие между объектом Vi s itor и элемен
тамиj структуры объектов. После того как объект Vi s itor представлен объекту
Ob ectS tructure, объект Obj ectStructure передает объект Visi tor методу accept объекта ConcreteE lement. Объект ConcreteElement передает сам себя методу v i s i t объекта Visitor, что позволяет этому объекту включить объект Vi s i tor в свои вычисления. Затем объект ConcreteElement передает объект Vi s itor другому объекту ConcreteElement , поэтому объект Vis itor может «посетить» его. При передаче объекта Vi s i tor другим объектам Соп creteElement цикл продолжается. Объект ConcreteElement может быть свя зан с любым количеством других объектов ConcreteElement. Он может пере давать объект Vis i tor нескольким, всем или ни одному связанному с ним объекту ConcreteElement.
I jObjectStructure I
|
1:accePt(v) |
|
|
.2:-. |
|
|
|
|
|
1 |
|
|
|
|
|
||
I |
|
|
|
|
accept(v) |
|
|
|
еl:СопсгеtеЕlemепt1 |
:1-------------------1:J |
|||||||
|
|
|
|
|
е2:СопсгеtеElеmепtZ |
|
||
|
1.1: visit(e1) |
L.._____ |
------ |
1.2.1: visщеl)1 |
||||
|
1 |
|
|
Ir- |
...Г'L --,--------J |
+ |
||
|
|
|
||||||
|
|
|
|
|
|
|||
|
Рис. 8.34. |
Взаимодействие в идеальной версии шаблона Visitor |
|
В этой версии шаблона Visitor объекты AbstractElement определяют, какие элементы структуры объектов «посещают» объект Vis itor и каков порЯдок
этих «посещений». Данная версия хорошо работает в тех случаях, когда объепКо
ты Visi tor любого вида, «посещая» элементы структуры объектов, следуют
одному и тому же маршруту. Преимуществоот здесь состоит в том, что класСЫ
Visi tor поддерживаются независимо способа организации структуры объ-
![](/html/2706/346/html_MxkKzTLKJz.Ja4Q/htmlconvd-LkZgZ6428x1.jpg)
![](/html/2706/346/html_MxkKzTLKJz.Ja4Q/htmlconvd-LkZgZ6429x1.jpg)
436 • Глава 8. Поведенческие шаблоны проектирования
меньших усилий. Если использование идеальной версии шаблона Visitor невоз_
можно, помещают в класс Vi s i tor (а не в его подклассы) как можно большую
часть логики, предназначенную ДЛЯ навигации по структуре объектов. Тогда число зависимостей таких объектов ConcreteVis i tor от структуры объектов будет минимальным, и сопровождение станет более простым.
СЛЕДСТВИЯ
© Шаблон Visitor позволяет легко добавлять в структуру объектов новые опе рации. Классы ConcreteElement не зависят от классов Vi s i tor, поэтомуАВ добавление нового класса Vis i tor не требует изменения класса
s t ractElement или любого из его подклассов.
©Шаблон Visitor помещает логику, необходимую ДЛЯ выполнения некоторой операции, в один сцепленный класс - ConcreteVi s i tor. Такая схема со провождается легче по сравнению с операциями, распределенными по мно
|
гим классам Сопсrе tеЕ lеmепt. |
© |
Единственный объект Vis i tor сохраняет состояние, необходимое для |
|
выполнения операции над структурами объектов. Такая схема легче сопро |
|
вождается и более эффективна по сравнению со схемой, при которой ин |
|
Формация о состоянии должна передаваться в виде дискретных значений |
® |
от одного объекта другому. |
Другое следствие использования шаблона Visitor состоит в том, что нужны |
|
|
дополнительные усилия для добавления новых классов ConcreteEl ement. |
|
Идеальная версия шаблона Visitor требует от программиста добавления но |
|
вого метода vis i t в каждый класс ConcreteVis i tor ДЛЯ каждого добав |
|
ляемого класса ConcreteEl ement. Для другой версии шаблона Visitor мо |
|
жет понадобиться изменение логики, используемой классами Vis i tor для |
® |
навигации по структуре объектов. |
Прямым следствием шаблона Visitor является то, что классы ConcreteEle |
|
|
men t должны обеспечивать предоставление о себе столько информации, |
|
сколько должно быть достаточно для проведения вычислений объектамИ |
|
Vis itor. Это может означать, что программист открывает информацию. |
|
которая в противном случае была бы скрыта инкапсуляцией класса. |
ПРИМЕР КОДА
Приведем коды ДЛЯ некоторых классов, представленных в проекте по созданиЮ
оглавления, описанном в разделе « Контекст». Сначала код для класОНса WordProcess or, содержащего общую логику ДЛЯ текстового процессора. отвечает за инициирование операций, манипулирующих документами.
public class WordProcessor {
/ / Редактируемый в дaHHЬ момент документ .
![](/html/2706/346/html_MxkKzTLKJz.Ja4Q/htmlconvd-LkZgZ6430x1.jpg)