代码之家  ›  专栏  ›  技术社区  ›  BCS

如何在访问者模式中传递“位置”信息?

  •  2
  • BCS  · 技术社区  · 16 年前

    假设我有一个这样的客人

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

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

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

    对不起,我第一次倒过来了(现在是 Accept Visit ). 现在匹配了 the pattern as show in Wikipedia

    所有访问方法如下所示:

    void Visit(IVisitor v) { v.Accept(this); }
    
    3 回复  |  直到 16 年前
        1
  •  2
  •   Mike Deck    16 年前

    在我看来,最简单的方法就是在访问者界面上有多个方法,每种类型的子对象有一个方法。孩子们是否是同一种语言类型并不重要,如果他们在语义上不同,他们应该用不同的方法来处理。

    您还应该尽量避免用visible结构的细节来污染Visitor实现。为了做到这一点,我将accept方法移到visible接口中,而不是在该接口上公开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)
      }
    }
    

    现在您将看到一个Visitor的实现,它有两种不同的方法,一种用于处理A子级,另一种用于处理B子级。

        2
  •  0
  •   David Koelle    16 年前

    基于你的架构,你应该打电话给 v.Visit(this) ,并让visible的实现决定如何使用 AChild BChild

    另外,考虑一下 B孩子 应该是Visitable实例的私有成员。

        3
  •  0
  •   Community CDub    7 年前

    从中的答案中提供以下附加信息 a background question

    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,它有一个Visit()方法,知道如何遍历AChild和BChild。