2

假设我有这样的访客

class Visitor : IVisitor
{
     void Accept(Visitable v)
     {
         /// other code
         v.AChild.Visit(this);
         v.BChild.Visit(this);
     }
}

其中 AChild 和 BChild 可以是完全相同的类型,但访问代码需要区分它们(它需要在 AChild 和 BChild 上进行不同的操作)。做这个的最好方式是什么?

  • 在访问者中设置状态并在下次调用时检查它
  • 将不同的访客传给每个孩子
  • 其他?

对不起,我第一次是倒着做的(当前AcceptVisit)。它现在匹配Wikipedia 中显示的模式

所有访问方法如下所示:

void Visit(IVisitor v) { v.Accept(this); }
4

3 回答 3

2

您仍然从我认为传统上使用该模式的方式向后命名方法。Visitable(或 Element)通常有一个 accept 方法,而 Visitor 有一个 visitX 方法。我将使用传统的命名方案以避免混淆自己:-)

IMO 最简单的方法是在您的访问者界面上使用多种方法,一种用于每种类型的孩子。孩子是否是相同的语言类型并不重要,如果它们在语义上不同,则应该通过不同的方法来处理。

您还应该尽量避免使用有关 Visitable 结构的详细信息来污染访问者实现。为了做到这一点,我会将 accept 方法向上移动到 Visitable 接口,而不是在该接口上公开 childA 和 childB。然后,Visitable 的每个实现都可以决定为每个孩子调用访问者上的哪个方法。这会将所有“位置”上下文传达给访问者,并为您提供一个不错的、干净的、解耦的解决方案。

这是我在想的一个例子。同样,我已将方法名称换回了我习惯的名称。

interface Visitable {
  accept(Visitor v)
}

interface Visitor {
  visitA(Node a)
  visitB(Node b)
}

class Container implements Visitable {
  private Node childA
  private Node childB

  ...
  void accept(Visitor v) {
    v.visitA(childA)
    v.visitB(childB)
  }
}

现在您将拥有一个具有 2 种不同方法的 Visitor 的实现,一种用于处理 A 孩子,另一种用于处理 B 孩子。

于 2009-02-09T22:41:45.090 回答
0

鉴于原始海报背景问题的答案中的以下附加信息:

The visitor object is required to know the structure of the things it visits. That's OK, though. You're supposed to write specialized visit operations for each type of thing the visitor knows how to visit. This allows the visitor to decide how much it really wants to visit, and in what order.

我会回答:创建一个特殊的 IVisitor 类,可能称为 ABChildVisitor,它有一个知道如何遍历 AChild 和 BChild 的 Visit() 方法。

于 2009-02-09T22:39:58.963 回答
0

根据您的架构,您应该只调用v.Visit(this),并让您的 Visitable 实现确定如何使用AChildand BChild

此外,请考虑这一点,AChild并且BChild可能应该是您的 Visitable 实例的私有成员。

于 2009-02-09T22:10:29.953 回答