Шаблон посетителя, почему это полезно?

1

Я использовал приведенный здесь пример посетителя. Где у нас есть:

.------------------------.
|        Flower          |
+------------------------+ 
| +accept(visitor)       |
| +pollinate(pollinator) |
| +eat(eater)            |
'------------------------'

У нас также есть Bug и Bee которые могут pollinate Flower и Predator который может eat цветок.

Используя шаблон vistor, я могу написать следующее:

bee = Bee()
fly = Fly()
worm = Worm()

# Using the visitor pattern:
for flower in flowerGen(10):    
    for object in [bee, fly, worm]:
        flower.accept(object)

Но код такой же читабельный и функциональный без посетителя:

# Without visitor pattern 
for flower in flowerGen(10):
    for object in [bee, fly, worm]:
        object.visit(flower)

Вопрос в том, какие преимущества предоставляют шаблон посетителя в этом примере?

Теги:
design-patterns
visitor

1 ответ

2

В статье, на которой вы ссылаетесь, довольно ясно, почему вы хотите использовать шаблон посетителя: когда вы не можете изменять объекты, потому что они происходят от третьего лица:

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

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

Заметим, что в статье соотношение обратное; вы не можете изменить иерархию Flower:

# The Flower hierarchy cannot be changed:

но класс поддерживает шаблон отправки посетителя через метод visit:

class Flower(object):
    def accept(self, visitor):
        visitor.visit(self)

Эта реализация может быть намного сложнее; пример был упрощен до простого visitor.visit() здесь, но на практике реальный шаблон посетителя может и делает гораздо больше на этом этапе.

Например, могут быть составные классы, которые содержат несколько подкомпонентов. Метод accept() затем будет делегировать далее эти подэлементы, чтобы затем при необходимости accept их на всех. Сохраняясь с цветочной темой, возможно, есть класс хризантемы или Далии, где некоторые посетители будут есть компоненты луча, в то время как другие хотели бы посетить компоненты в глазу, чтобы опылять. Это до составного объекта, чтобы направить каждого посетителя на эти части по отдельности.

Если вы ищете конкретные примеры, посмотрите на модуль ast, который предлагает класс NodeVisitor который должен быть подклассифицирован, чтобы добавить методы, позволяющие вам настроить, как обрабатывается дерево AST. Я использовал конкретный подкласс NodeTransformer чтобы изменить способ работы кода Python несколько раз. Здесь шаблон посетителя используется для эффективного фильтрации определенных типов в более крупной иерархии, что значительно упрощает код обработки АСТ без необходимости изменять какой-либо из классов узлов АСТ.

  • 0
    Как в моем контрпримере я изменил иерархию цветов?
  • 0
    @nowox: нет, но вы предполагаете, что метод accept() всегда будет простой отправкой. Обновлено.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню