python - 访客模式,为什么有用?

标签 python design-patterns visitor-pattern

我使用了给出的访客示例 here我们在哪里有这个:

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

我们还有一个Bug和一个Bee,它们可以授粉Flower和一个可以花的捕食者

使用访问者模式我可以这样写:

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)

问题是,此示例中的访问者模式有哪些优势?

最佳答案

您链接到的文章非常清楚地说明了为什么要使用访问者模式:当您无法更改对象,因为它们来自第三方:

The assumption is that you have a primary class hierarchy that is fixed; perhaps it’s from another vendor and you can’t make changes to that hierarchy. However, your intent is that you’d like to add new polymorphic methods to that hierarchy, which means that normally you’d have to add something to the base class interface. So the dilemma is that you need to add methods to the base class, but you can’t touch the base class. How do you get around this?

当然,如果您可以为蜜蜂、苍蝇和蠕虫添加一个 visit 方法,那就没问题了。但是当您不能时,使用访问者模式是下一个最佳选择。

请注意,在文章中,关系是相反的;您无法更改 Flower 层次结构:

# The Flower hierarchy cannot be changed:

但是该类确实通过visit方法支持访问者调度模式:

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

该实现可能要复杂得多;该示例已简化为简单的 visitor.visit() 调用此处,但实际上,真正的访问者模式在此阶段可以而且确实可以执行更多操作。 p>

例如,可能有复合类,其中包含多个子组件。然后,accept() 方法将进一步委托(delegate)给这些子元素,然后根据需要对所有子元素调用 accept。与花卉主题保持一致,也许有一个 Chrysanthemum or Dahlia class ,一些游客会吃掉射线成分,而其他人则想访问眼睛中的成分来授粉。由复合对象将每个访问者单独引导至这些部分。

如果您正在寻找具体示例,请查看 ast module ,它提供了 NodeVisitor class应该对其进行子类化以添加方法,以便您自定义传入的 AST 树的处理方式。我已经使用了特定的NodeTransformer subclass改变 Python 代码在 several 上的工作方式occasions 。这里,访问者模式用于有效地过滤掉更大层次结构中的某些类型,从而极大地简化了 AST 处理代码,而无需更改任何 AST 节点类本身。

关于python - 访客模式,为什么有用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50854142/

相关文章:

python - 我怎样才能让 virtualenv 使用 Enthought Python Distribution 生成具有正确 sys.path 的 Python 可执行文件?

Python GTK - 将鼠标点击传递到下面的窗口

asp.net - 工厂方法模式澄清

oop - 翻译模式

c++ - 访问者模式是否比受控使用 RTTI 更好?

python - 如何将 (x,y) 对列表映射到 Pool.map 中的函数 f(x,y)?

java - 父包装子类方法

Python Pythonic 方式来组织/设计 if 语句

c++ - C++中访问者模式的层次结构实现

python - 将字符串分成 3 个字符的组