访客模式,为什么有用?

Visitor Pattern, why is it useful?

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

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

我们还有一个Bug和一个Bee可以pollinate一个Flower,一个Predator可以eat一个花。

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

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)

问题是,这个例子中的访问者模式有什么优势?

您 link 阅读的文章非常清楚您为什么要使用访问者模式:当您 无法更改对象时,因为它们来自第三方:

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:

但是 class 通过 visit 方法支持访问者调度模式:

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

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

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

如果您正在寻找具体示例,请查看 ast module, which offers a NodeVisitor class which should be subclassed to add methods to let you customise how the AST tree passed in is being processed. I've used the specific NodeTransformer subclass to alter how Python code works on 。这里访问者模式用于有效地过滤掉更大层次结构中的某些类型,大大简化了 AST 处理代码,而无需更改任何 AST 节点 classes 本身。