【问题标题】:Visitor Pattern, why is it useful?访客模式,为什么有用?
【发布时间】:2018-06-14 17:52:52
【问题描述】:

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

.------------------------.
|        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)

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

【问题讨论】:

    标签: python design-patterns visitor-pattern


    【解决方案1】:

    您链接到的文章非常清楚您为什么要使用访问者模式:当您由于对象来自第三方而无法更改对象时

    假设您有一个固定的主要类层次结构;也许它来自另一个供应商,您无法更改该层次结构。但是,您的意图是您想向该层次结构添加新的多态方法,这意味着通常您必须向基类接口添加一些东西。所以困境是你需要在基类中添加方法,但你不能触及基类。你如何解决这个问题?

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

    注意,文章中的关系是颠倒的;你不能改变Flower 层次结构:

    # The Flower hierarchy cannot be changed:
    

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

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

    这种实现可能要复杂得多;该示例已被简化为一个简单的visitor.visit() 调用here,但在实践中,真正的访问者模式在这个阶段可以而且确实做得更多。

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

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

    【讨论】:

    • 在我的反例中我如何改变花的层次结构?
    • @nowox:你不知道,但你假设accept() 方法总是一个简单的调度。已更新。
    • 好的,所以这个例子并不是理解这种模式的最佳选择。我需要考虑一个没有反例的例子
    • @nowox:我为你添加了一个复合示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多