Java “一个访客是怎么做的?”;“定义新操作”;以迭代器没有的方式?
我知道并经常使用迭代器和访问者,在我听说GangofFour的设计模式之前,我就已经使用了这两种方法。虽然这两种模式的语法非常不同,但我使用这两种模式的目的是相同的:遍历一组对象。粗略地说,当我有相同类型的非结构化对象时,我使用迭代器,当我有不同类型的结构化对象时,我使用访问者。对我来说,访问者只是一个优雅、奇特、更强的类型化迭代器 当我阅读设计模式时,我注意到对访问者的描述,尤其是它与迭代器描述的区别 Visitor允许您定义一个新操作,而无需更改其操作的元素的类 迭代器:提供一种顺序访问聚合对象元素的方法,而不公开其底层表示 从那以后,我一直在考虑这个问题,但我真的不知道访问者是如何定义一个新操作的 例如,如果我想实现一个相当简单的操作,比如Java “一个访客是怎么做的?”;“定义新操作”;以迭代器没有的方式?,java,algorithm,design-patterns,iterator,visitor,Java,Algorithm,Design Patterns,Iterator,Visitor,我知道并经常使用迭代器和访问者,在我听说GangofFour的设计模式之前,我就已经使用了这两种方法。虽然这两种模式的语法非常不同,但我使用这两种模式的目的是相同的:遍历一组对象。粗略地说,当我有相同类型的非结构化对象时,我使用迭代器,当我有不同类型的结构化对象时,我使用访问者。对我来说,访问者只是一个优雅、奇特、更强的类型化迭代器 当我阅读设计模式时,我注意到对访问者的描述,尤其是它与迭代器描述的区别 Visitor允许您定义一个新操作,而无需更改其操作的元素的类 迭代器:提供一种顺序访问聚合
toLocalizedString()
,作为toString()
的本地化替代方案。当您将访问者传递给元素时,它将遍历该对象的整个子结构。此外,您不能从accept/visit方法返回任何内容。这些特征中的每一个都阻止我使用访问者定义toLocalizedString()
这就引出了我的问题:访问者如何以迭代器所没有的方式“定义一个新的操作”如果我相信四人帮的描述,我觉得我错过了访问者模式的真正功能。遍历结构不是访问者模式的定义特性。事实上,可以将访问者作为一个奇特的迭代器来使用结构遍历对象
访问者与迭代器的区别在于访问者允许您执行所谓的操作,即将消息路由到一个方法,该方法取决于所访问对象的运行时类型和访问者对象。被访问的对象在访问者外部,但操作的可执行代码包含在访问者内部。换句话说,遵循访问者模式可以执行被访问对象外部的操作,这可以被认为是在对象上定义了新操作。您已经确定了以下原因,即无法对访问者引入新操作:
visit
和accept
返回一个boolean
,指示是否应继续探索结构。然后,您可以让accept
像这样工作(在伪代码中):
这样,一旦访问者意识到它已经完成了,它就可以停止搜索。这类似于对链接在一起的对象执行深度优先、回溯搜索
然而,对于第(2)项,我认为您缺少了访问者的一项重要技术——因为访问者是对象,它们可以包含私有状态信息。例如,假设我想编写一个简单的count
函数,返回结构中的元素总数。然后我可以这样写:
public int count(Base object) {
Visitor v = new Visitor() {
private int numElems = 0;
public void visit(Base object) {
numElems++;
}
public void visit(Derived1 object) {
numElems++;
}
// ... etc
public int getCount() {
return numElems;
}
};
object.accept(v);
return v.getCount();
}
请注意,即使在这里visit
和accept
returnvoid
,我仍然可以构建一个整体方法,通过让访问者保持内部状态,然后在访问完成后返回该状态来返回值。从现在起,调用count(obj)
wil;返回所有对象的计数,本质上是将额外的方法“嫁接”到类层次结构中
希望这有帮助 谢谢。我知道布尔技巧,但它本质上只是一个
if(..)break代码>在迭代器中。同样地,count元素也可以很容易地用迭代器通过int count来计算;对于(每个元素)计数++代码>@bitnus-我同意。我的意思是要表明你对访客模式局限性的担忧是没有道理的。您可以想象,通过使用私有状态技巧,并结合基于每种类型获取本地化字符串的自定义实现,可以执行一个更精细的操作,如toLocalizedString
。如果你有一个迭代器,你不能不写一个巨大的级联“如果是这个类型,做这个,如果是那个类型,做那个,…”这样做有意义吗?
public int count(Base object) {
Visitor v = new Visitor() {
private int numElems = 0;
public void visit(Base object) {
numElems++;
}
public void visit(Derived1 object) {
numElems++;
}
// ... etc
public int getCount() {
return numElems;
}
};
object.accept(v);
return v.getCount();
}