为什么我们在访问者DP中同时需要accept
和visit
个功能?如果我们采用典型的例子:
class Visitor {
visit(A a) { }
visit(B b) { }
}
interface Element {
accept(Visitor v);
}
class A implements Element {
accept(Visitor v) {
v.visit(this); // will call visit(A)
}
}
class B implements Element {
accept(Visitor v) {
v.visit(this); // will call visit(B)
}
}
要使用访问者DP,我们的v
实例Visitor
以及e
的实例Element
,我们会这样做:
e.visit(v)
简单地调用
v.visit(e)
那为什么我们不能简单地进行第二次调用并绕过中介功能呢?由于我认为GoF并不愚蠢,我想我错过了一些东西。它是什么?
答案 0 :(得分:3)
Here是访问者模式的绝佳参考,其中提到了以下内容:
当在程序中调用accept()方法时,它的实现 是根据两者选择的:
- 元素的动态类型。
- 访客的静态类型。
当调用关联的visit()方法时,它的实现是 根据两者选择:
- 访客的动态类型。
- 从accept()方法的实现中已知的元素的静态类型,它与 动态类型的元素。 (作为奖励,如果访客无法处理 给定元素类型的参数,然后编译器将捕获 错误。)
因此,选择了visit()方法的实现 两者:
- 元素的动态类型。
- 访客的动态类型。
然后他们继续提到以下内容:
这有效地实现了双重派遣......
通过这种方式,可以编写单个算法来遍历图形 元素和许多不同类型的操作都可以执行 在那次遍历期间,提供不同类型的访客 基于两者的动态类型与元素交互 元素和访客。
可以在Java汽车示例中看到:
class Car implements CarElement {
CarElement[] elements;
// ...
public void accept(CarElementVisitor visitor) {
for(CarElement elem : elements) {
elem.accept(visitor);
}
visitor.visit(this);
}
}
总而言之,在您的示例中,您不会从原始DP实现中获得太多好处,但如果示例更复杂,例如它的Composite具有几个内部实现的Element(如Java)上面的汽车示例),然后它可以将访问者行为应用于其部分或全部内部元素。
根据对原始问题的评论,此模式分为两部分:
我强烈推荐以下设计模式书,因为它真正简化了许多概念。 GoF书有时太过学术化了。
根据这本书,以下是使用访客的利弊:
(在所用示例的上下文中)
赞成
CON外
答案 1 :(得分:0)
它很简单(但也许有点令人困惑),访问者模式的重点是将访问者与访问者分开。
accept()允许被访问者选择它将向某个类型的访问者公开的行为。
布拉迪说同样的话,我只是想用更少的话说出来