答案 0 :(得分:37)
<强>单调度强>
假设Node是一个接口类,两个子类是接口的具体实现。
如果在节点实例上调用GenerateCode()
方法,则执行的实际操作取决于节点的类型。它可以是VariableRefNode
或AssignmentNode
中的方法。如果您致电PrettyPrint()
,情况也是如此。因此,执行的实际操作取决于您正在调用的方法的名称以及节点的类型。
<强>双调度强>
这次Node
允许您将NodeVisitor
类型的参数传递给名为Accept
的方法。在程序中,如果在节点实例上调用Accept
,则现在执行的实际操作取决于节点的类型(VariableRefNode
或AssignmentNode
)< strong> AND 您传入Accept
(TypeCheckingVisitor
或CodeGeneratingVisitor
)的访问者实例的类型。
答案 1 :(得分:20)
元素对象的accept
方法接收访问者对象,并在访问者对象上调用visit
方法。由于访问者对象具有多个visit
方法,因此基于元素类型调用适当的visit
方法。这里我们有两个调用(双调度),为元素指定元素和右操作(基于其类型)。
答案 2 :(得分:6)
嗯,这是该文章的相关引用:
访客实施“双重调度”。 OO消息通常表现为“单一调度” - 执行的操作取决于:请求的名称和接收者的类型。在“双重调度”中,执行的操作取决于:请求的名称,以及TWO接收者的类型(访问者的类型及其访问的元素的类型)。
这实质上意味着不同的访问者可以访问相同类型,同一访问者可以访问不同类型。使用访客模式执行的命名操作的效果可能取决于访问者和访问者(双重调度)。
答案 3 :(得分:0)
示例代码,显示了双重调度:
import java.util.Arrays;
import java.util.List;
class Client {
public static void main(String[] args) {
List<Node> nodes = Arrays.asList(new NodeA(), new NodeB());
List<NodeVisitor> visitors = Arrays.asList(new NodeVisitor1(), new NodeVisitor2());
for (Node node : nodes) {
for (NodeVisitor visitor : visitors) {
node.accept(visitor);
}
}
}
}
interface Node {
void accept(NodeVisitor visitor);
}
interface NodeVisitor {
void visit(Node node);
}
class NodeA implements Node {
@Override
public void accept(NodeVisitor visitor) {
visitor.visit(this);
}
@Override
public String toString() {
return "Node A";
}
}
class NodeB implements Node {
@Override
public void accept(NodeVisitor visitor) {
visitor.visit(this);
}
@Override
public String toString() {
return "Node B";
}
}
class NodeVisitor1 implements NodeVisitor {
@Override
public void visit(Node node) {
System.out.println("Node visitor 1, node " + node);
}
}
class NodeVisitor2 implements NodeVisitor {
@Override
public void visit(Node node) {
System.out.println("Node visitor 2, node " + node);
}
}
输出为:
Node visitor 1, node Node A
Node visitor 2, node Node A
Node visitor 1, node Node B
Node visitor 2, node Node B