为什么要使用访客模式?

时间:2008-12-12 00:51:49

标签: design-patterns visitor

重复:When Should I Use The Visitor Design Pattern

为什么有人想要使用访客模式?我读了几篇文章,但我没有得到什么。

如果我需要一个功能来计算自定义,我可以使用

Custom.Accept(BillVisitor)

或类似

Bill(Customer)

第二个不太复杂,Bill函数仍然与Customer类分开。那么我为什么要使用访客模式?

5 个答案:

答案 0 :(得分:49)

当你有一个复杂的结构,即层次结构或其他不仅仅是线性的结构时,问题就出现了。如果你不能简单地遍历结构,访问者就会非常方便。

如果我有一个层次结构(或树),每个节点都有一个子列表。当我想将一个过程应用于树中的每个节点时,创建一个访问者是很愉快的。

然后,节点可以将访问者应用于自身及其每个子节点。过渡性地,每个孩子都做同样的事情(将访客应用于自己,然后应用于任何孩子)。

这种访问者的使用非常好。

如果您拥有超简单的数据结构,则访问者不会添加大量值。

答案 1 :(得分:15)

访问者模式是对不支持多个调度的语言的攻击(C ++和Java等语言仅支持基于对象的单一调度.CLOS支持多个调度)。在这种情况下,如果您希望Bill和Customer都是多态的,那么您必须使用单一调度语言中的两个接口BillVisitor和Customer。例如:accept的实现通常是:

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

请注意,Customer#accept和BillVisitor#bill都可以被它们各自的子类覆盖,从而产生非常丰富的运行时行为组合,否则无法实现。它实际上是大多数其他人在此描述的替代结构的超集,它将功能应用于复杂的数据结构。

答案 2 :(得分:3)

在我的CAD / CAM应用程序中,我有路径和路径集合(PathList)。有时我必须生成一组形状。不仅我必须生成这个特定的形状集合,我必须将它包含在另一个形状集合中。我经常需要十几个或更多参数来传达进行计算所需的所有信息。

我的CAM中的所有形状计算(简单或复杂)都是一个发送到不同机器的PathList。

通过这种设计,最好有一些设置,包括将结果添加到单个集合中。

Path Visitor非常适合。每个形状计算都封装在它自己的类中,其属性与所需的属性一样复杂。

所以Kitchen Hood Visitor可能有8个形状到Pathlist

虽然厨房柜台访客增加了6个形状。

抽屉访客增加了一些。

然后我将生成的PathList传递给系统的其余部分,就像任何其他形状生成器一样。

我可以通过添加其他访问者或不运行某些访问者来轻松选择。对于一个只想要一个柜台和抽屉的人,我只需要两个访客。

结果代码非常易读,这对于我在3年,5年或10年后再次访问此区域非常重要。此外,由于封装,对一位访问者的更改对其他访问者的影响微乎其微。

此外,我现在有一个标准化的设计模式,通过实现访问者模式将任何新功能添加到PathList。

例如,过去我们的属性编辑器只在单个路径上工作。当我们改为编辑多个路径时,很容易实现自定义访问者对所有路径进行全局更改。在委托内部使用for循环时,它更具可读性。

但最终归结为判断和偏好。

答案 3 :(得分:2)

访客的另一个好处是,它们很容易扩展,如果您的语言允许,您甚至可以使用lambdas来清理。

答案 4 :(得分:1)

在这两种情况下,访客都与客户类分开。如果您想从调用者类中抽象访问者,那么优势就在于此。在第二种情况下,呼叫类必须知道计费。你可以在某处返回另一个例程来返回一个IVisitor。然后调用代码可以调用Custom.Accept(IVisitor),而不知道访问者正在做什么。

基本上在这种情况下和S.Lott提到的案例中,您可以将访客视为代表。这是一个可以像对象一样传递并在需要的地方使用的函数。