为什么访问者负责枚举访问者模式中的子项?
根据我发现的代码,访问者似乎需要了解所访问对象的结构并调用所需的子对象。 在某些情况下,即使访问的类被修改,访问者仍希望继续工作,这似乎有点笨拙。
我想真正的问题是:他们的枚举是由访问的代码而不是访问者代码完成的吗?
Based on the code I've found, it seems that the Visitor is required to known the structure of the visited objects and call on the needed children. This seems a bit clunky in some cases where the visitor would want to continue to work even if the visited classes are modified.
I guess the real question is: Is their a pattern where the enumeration is done by the visited code rather than the visitor code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
访问者对象需要知道它访问的事物的结构。 不过没关系。 您应该为访问者知道如何访问的每种类型的事物编写专门的访问操作。 这使得访问者可以决定自己真正想要访问的程度以及访问顺序。
假设你有一棵树。 一个访问者可能会进行前序遍历,一个访问者可能会进行中序遍历,而另一位访问者可能只对叶节点进行操作。 访问者类可以完成所有这些事情,而不需要对树类进行任何更改。
访问者知道该结构,但这并不一定意味着访问者执行的操作知道所有结构。 您可以将访问者与命令组合起来。命令。 为访问者对象提供一个命令对象,访问者将在其访问的每个对象上调用该命令。
如果您想要进行简单的操作并让集合为您提供要操作的每个项目,那么您希望集合为自己提供一个迭代器。 对迭代器为您提供的每件事调用您的函数。
如果您想以不同的顺序迭代树的节点,那么树将需要提供多个迭代器。 如果您想按照树尚不支持的顺序处理节点,则需要修改树类。
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.
Suppose you have a tree. One visitor might do a pre-order traversal, one might do an in-order traversal, and yet another visitor might act only on leaf nodes. The visitor classes can do all these things without requiring any changes to the tree class.
The visitor knows the structure, but that doesn't necessarily mean the operation the visitor performs knows all the structure. You might combine a visitor with a command. Give the visitor object a command object, and the visitor will invoke the command on each thing it visits.
If you want to have a simple operation and let the collection give you each item to act on, then you want the collection to provide an iterator for itself. Call your function on each thing the iterator gives you.
If you want to iterate over the tree's nodes in various orders, then the tree will need to offer multiple iterators. If you want to process nodes in an order that the tree doesn't already support, you'll need to modify the tree class.
是的。 被访问的对象可以进行枚举(即调用所需的子对象)。 这仍然称为“Visitor”模式(事实上,设计模式的第一个 Visitor 示例就是这样做的)。 我编造的示例片段:
注意:对于拜访孩子们,我们不能说
visitor.visit(n);
。 这是因为 Java 不是动态选择方法(根据其参数的运行时类),而是静态选择方法(根据其参数的编译时类型)。Yes. The visited objects can do the enumeration (i.e. call on the needed children). This is still called the "Visitor" pattern (in fact, Design Pattern's first sample of Visitor does it this way). My made-up example snippet:
Note: for visiting the children, we can't say
visitor.visit(n);
. This is because Java does not dynamically select the method (based on the runtime class of its arguments), but selects the method statically (by the compile-time type of its arguments).简而言之,我认为访问者模式与枚举的完成方式正交。 可以用任何一种方式完成,也可以根本不进行枚举。
我认为访问者需要知道访问的结构由哪些元素组成。 想知道汽车由车轮和发动机组成。 我认为没有必要知道它们到底是如何组合的。 考虑以下示例。 Insider 知道访问的对象结构并自行执行枚举。 局外人不知道这一点,并将枚举委托给访问的对象。
我有一个项目广泛使用访问者模式,根本没有任何枚举。 我们有基本接口 Field 和许多实现它的类,如 StringField、NumberField 等。很多时候我们必须根据字段类型做不同的事情,例如以不同的方式呈现它、从 DB 加载、导出到 xml 等我们可以在 Field 接口中定义方法,但这会使其与项目的每个功能相结合 - 可怜的字段必须了解导出、导入、渲染为 html 和 rtf 等。我们也可以使用 instanceof 但可能的集合。实现 Field 接口的类随着时间的推移而改变,并且有可能添加新的字段类型并忘记
在某个地方添加。 所以我们决定使用访问者模式,就像
任何 Field 实现都需要有方法
一样,如果我添加 Field 接口的新实现,我必须以某种方式实现它。 通常
这是新添加的类的地方。 这迫使我添加
到 FieldVisitor 接口,这使我在我们已有的每个 FieldVisitor 实现中实现它。 所以如果我忘记做一些事情 - 我会得到编译器错误。
这种情况下的枚举(如果有的话)是在访问的结构和访问者之外完成的。 但我仍然认为这是访客模式的一个有效案例。
它实施起来有点困难,但使用起来更容易、更安全。
In short words, I think that Visitor pattern is orthogonal to the way enumeration is done. It can be done either way, or no enumeration at all.
I think that visitor is required to know what elements visited structure consists of. Like to know that car consists of Wheels and Engine. To know how exactly they are combined is not necessary, I think. Consider following example. Insider knows visited object structure and performs enumeration itself. Outsider does not know it and delegates enumeration to the visited object.
I had a project with wide usage of visitor pattern without any enumeration at all. We had base interface Field and many classes implementing it, like StringField, NumberField, etc. Very often we had to do different things based on the field type, for example render it in a different way, load from DB, export to xml, etc. We could define methods in Field interface, but that would make it coupled with every single feature of the project - poor field has to know about exporting, importing, rendering to html and rtf, etc. We also could use instanceof but set of possible classes implementing Field interface was changed over time and it was possible to add new field type and forget to add
somewhere. So we decided to use visitor pattern, and it was like
As any Field implementation is required to have method
then if I add new implementation of Field interface, I have to implement it somehow. Normally it is
where this is a newly added class. This forces me to add
to FieldVisitor interface, which makes me implement it in every FieldVisitor implementation that we already have. So if I forget to do something of this - I'll get compiler error.
Enumeration in this case, if any, was done outside of visited structure and visitor. But I still think about it as a valid case of visitor pattern.
It happend to be a little bit harder to implement, but easier and safer to use.
分层访问者模式解释了一种不同的方法,它添加了进入和离开级别的事件。 关联的讨论页面提供访问者或容器内迭代的参数。 它包括使用外部迭代器的建议,如果您有一个常规树并且需要以不同方式进行迭代,这对我来说很有意义。
回顾我的 oofRep 访客,它有一系列不同类别的级别访问并在方法中进行迭代,例如:
使用覆盖
The Hierarchical Visitor Pattern explains a different approach where it adds events for entering and leaving levels. The associated discussion page presents arguments for iteration being within the visitor or the container. It includes a suggestion of using an external iterator which makes sense to me if you have a regular tree and need to iterate differently.
Looking back to my oofRep visitor it had a series of levels of different classes to visit and had the iteration within methods like:
with an override
看看这篇文章中的解释。
来自 Wiki:
Have a look at the explanation in this article.
From Wiki: