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

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
Посетитель
Visitor
Тип поведенческий
Назначение не изменяя основного класса, добавить в него новые операции.
Структура
Применяется в случаях когда необходимо для ряда классов сделать похожую (одну и ту же) операцию.
Плюсы
  • новая функциональность в несколько классов добавляется сразу, не изменяя код этих классов;
  • позволяет получить информацию о типе объекта;
  • двойная диспетчеризация;
  • возможность описания своего алгоритма для каждого типа объектов.
Минусы
  • при изменении обслуживаемого класса нужно поменять код у шаблона;
  • затруднено добавление новых классов, поскольку нужно обновлять иерархию посетителя и его сыновей.
Описан в 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().

C++[править | править код]

Java[править | править код]

Kotlin[править | править код]

C#[править | править код]

PHP[править | править код]

Python[править | править код]

Delphi[править | править код]

Swift[править | править код]

Литература[править | править код]

  • Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес. Приемы объектно-ориентированного проектирования. Паттерны проектирования. — СПб.: Питер, 2001. — 368 с. — ISBN 5-272-00355-1.

Ссылки[править | править код]