Обзор темы [Шаблоны проектирования]

Затем: МотивацияНазначение

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

Затем: СтруктураМотивация

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

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

Эта диаграмма показывает часть иерархии класса Node. Проблема в том, что распределение всех этих операции между различными классами  вершин графа ведет к системе, сложной для понимания, поддержки и изменения. Кроме того, добавляя новую операцию обычно требуется перетранслирование всех этих классов. Было бы лучше, если каждая новая операция могла бы быть добавлена отдельно, и классы вершин, не зависели бы от операций, которые обращаются к ним.

Мы можем обеспечить это, инкапсулируя связанные операции из каждого класса в отдельном объекте, называемом посетителем(visitor), и передавая его элементам абстрактного дерева синтаксиса. Когда элемент "принимает" посетителя, он посылает запрос посетителю, который кодирует класс посетителя. Затем посетитель выполняет операцию для этого элемента.

Например, компилятор, который не использовал посетителей, мог бы контроль соответствия типов вызывая операцию TypeCheck для ссылки на дерево синтаксиса. Каждый из узлов выполнил бы TypeCheck, вызывая TypeCheckon для его компонента. Если бы использовался механизм посетителей, был бы создан объект TypeCheckingVisitor и обращение к операции Accept на дереве синтаксиса с этим объектом в качестве параметра. Каждая вершина выполнила бы операцию с помощью обратного вызова visitor-у: узел присваивания вызывал бы операцию VisitAssignment посетителя, еременная ссылка вызывала бы VisitVariableReference. Проверка типов TypeCheck в узле присваивания AssignmentNode теперь представляется операцией VisitAssignmentoperation на TypeCheckingVisitor.

Расширяя возможности посетителя мы нуждаемся в абстракном родительском классе NodeVisitor для всех посетителей дерева синтаксиса. NodeVisitor должен объявить операцию для каждого класса узла. Приложение, которое должно вычислить метрики программы определит новые подклассы NodeVisitor и больше не будет нуждаться в специфическом код. Шаблон Посетитель инкапсулирует операции для каждой фазы трансляции в Visitor-а, ассоциированного с этой фазой.

Затем: Составные частиСтруктура

Составные части