2008-12-12 3 views
27

Дубликат: When Should I Use The Visitor Design PatternЗачем использовать шаблон посетителя?

Почему кто-то хочет использовать шаблон посетителя? Я прочитал пару статей, но я ничего не получаю.

Если мне нужна функция, чтобы выставить счет обычай, я мог бы использовать

Custom.Accept(BillVisitor) 

или что-то вроде

Bill(Customer) 

Второй является менее сложным, а функция Билл по-прежнему отделена от Клиента класс. Так почему я хотел бы использовать шаблон посетителя?

+1

См. Также http://stackoverflow.com/questions/255214/when-should-i-use-the-visitor-design-pattern – 2008-12-12 01:26:44

ответ

49

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

Если у меня есть иерархия (или дерево), каждый Узел имеет список детей. Когда я хочу применить процесс к каждому узлу в дереве, приятно создать посетителя.

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

Это использование посетителя работает очень красиво.

Когда у вас есть сверхпростая структура данных, посетитель не добавляет большого значения.

+1

Одним из примеров такой сложной структуры является дерево синтаксиса в компиляторе. – Shuo 2012-07-13 21:54:18

1

В обоих случаях посетитель отделен от класса клиента. Преимущество было бы, если бы вы хотели отвлечь посетителя от класса вызывающего. Во втором случае вызывающий класс должен знать о выставлении счетов. Вместо этого у вас может быть другая процедура, которая вернет IVisitor. Вызывающий код может затем вызвать Custom.Accept (IVisitor) и не знать ничего о том, что делает посетитель.

В основном в этом случае и в случае упомянутого S.Lott вы можете думать о посетителе, как о делегате. Это функция, которую вы можете передавать как объект и использовать там, где это необходимо.

2

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

16

Шаблон посетителя - это взлом для языков, которые не поддерживают сразу несколько отправки (язык, такой как C++ и Java, поддерживает только одну отправку на основе объекта. Несколько диспетчеров поддерживаются CLOS). В этом случае, если вы хотите, чтобы и Bill, и Customer были полиморфными, вам придется использовать два интерфейса, BillVisitor и Customer на отдельных языках рассылки. Например: реализация принимают, как правило:

void accept(BillVisitor visitor) { visitor.bill(this); } // java syntax 

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

3

В моем приложении CAD/CAM у меня есть пути и коллекции путей (PathList). Иногда мне приходится создавать коллекцию фигур.Я не только должен генерировать эту конкретную коллекцию форм, я должен включить ее в другую коллекцию фигур. Мне часто требуется дюжина или более параметров для передачи всей информации, необходимой для проведения расчетов.

Все вычисления формы (простые или сложные) в моем CAM направляют PathList, который отправляется на разные машины.

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

The Path Visitor подходит для этого красиво. Каждое вычисление формы инкапсулируется в собственный класс с такими сложными свойствами, как необходимые.

Так вытяжкой посетитель может было 8 фигур в Pathlist

Хотя Кухня Счетчик посетителей добавляет 6 формы.

Ящик Посетитель добавляет еще несколько.

Затем я передаю полученный PathList остальной системе, как любой другой генератор формы.

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

Полученный код очень читабельен, что важно, когда я пересматриваю эту область на 3, 5 или 10 лет по линии. Кроме того, из-за инкапсуляции изменения к одному посетителю имеют минимальное влияние на других посетителей.

Кроме того, теперь у меня есть стандартизованный шаблон проектирования, чтобы добавить любые новые функции в PathList, реализовав шаблон посетителя.

Например, когда-то наш редактор свойств работал только по одному пути. Когда мы перешли на редактирование нескольких путей, было легко реализовать пользовательских посетителей для глобальных изменений ко всем путям. Это было более читаемо, а затем использовалось для циклов внутри делегатов.

Но в конечном счете это сводится к суждению и предпочтению.

Смежные вопросы