Посетитель (шаблон проектирования)

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск
Шаблон проектирования
Посетитель
Visitor
Тип:

поведенческий

Назначение:

не изменяя основного класса, добавить в него новые операции.

Структура:

VisitorDiagram.svg

Применяется в случаях:

когда необходимо для ряда классов сделать похожую (одну и ту же) операцию.

Плюсы:
  • новая функциональность в несколько классов добавляется сразу, не изменяя код этих классов;
  • позволяет получить информацию о типе объекта;
  • двойная диспетчеризация;
  • возможность описания своего алгоритма для каждого типа объектов.
Минусы:
  • при изменении обслуживаемого класса нужно поменять код у шаблона;
  • затруднено добавление новых классов, поскольку нужно обновлять иерархию посетителя и его сыновей.
Описан в Design Patterns

Да

Посетитель (англ. visitor) — поведенческий шаблон проектирования, описывающий операцию, которая выполняется над объектами других классов. При изменении visitor нет необходимости изменять обслуживаемые классы.

Шаблон демонстрирует классический приём восстановления информации о потерянных типах, не прибегая к понижающему приведению типов.

Решаемая проблема[править | править вики-текст]

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

Задача[править | править вики-текст]

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

Решение[править | править вики-текст]

Для независимости посетитель имеет отдельную иерархию. Структуры имеют некий интерфейс взаимодействия.

Использование[править | править вики-текст]

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

Создается базовый класс Visitor с методами visit() для каждого подкласса родительского Element. Добавьте метод accept(visitor) в иерархию Element. Для каждой операции, которая должна выполняться для объектов Element, создайте производный от Visitor класс. Реализации метода visit() должны использовать открытый интерфейс класса Element. В результате: клиенты создают объекты Visitor и передают их каждому объекту Element, вызывая accept().

Рекомендации[править | править вики-текст]

Шаблон следует использовать, если:

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

Преимущества и недостатки[править | править вики-текст]

Преимущества:

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

Недостатки:

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

Реализация[править | править вики-текст]

  1. Добавьте метод accept(Visitor) в иерархию «элемент».
  2. Создайте базовый класс Visitor и определите методы visit() для каждого типа элемента.
  3. Создайте производные классы Visitor для каждой операции, исполняемой над элементами.
  4. Клиент создаёт объект Visitor и передаёт его в вызываемый метод accept().

Ссылки[править | править вики-текст]