我正在研究与访问者模式相关的其他问题,但无法理解访问者模式中双重调度的实现。
请参考链接 访客模式
访客模式中的双重调度如何工作?
单次派送
假设 Node 是一个接口类,两个子类是接口的具体实现。
如果您GenerateCode()
在节点实例上调用方法,则执行的实际操作取决于节点的类型。它可以是VariableRefNode
或中的方法AssignmentNode
。如果你打电话也是一样的PrettyPrint()
。因此,实际执行的操作取决于您正在调用的方法的名称和节点的类型。
双重派送
这一次Node
允许你将一个类型的参数传递NodeVisitor
给它的名为Accept
. 在您的程序中,如果您调用Accept
节点实例,现在执行的实际操作取决于节点的类型(VariableRefNode
或AssignmentNode
)和您传入的访问者实例的类型Accept
(TypeCheckingVisitor
或CodeGeneratingVisitor
)。
元素对象的accept
方法接收一个访问者对象并调用访问者对象的visit
方法。由于访问者对象有多种visit
方法,因此根据元素类型visit
调用适当的方法。这里我们有两个调用(double dispatch)来指定元素和元素的正确操作(基于它的类型)。
好吧,这是那篇文章的相关引述:
访客实现“双重调度”。OO 消息通常表现为“单次调度”——执行的操作取决于:请求的名称和接收者的类型。在“双重调度”中,执行的操作取决于:请求的名称,以及两个接收者的类型(访问者的类型和它访问的元素的类型)。
这实质上意味着不同的访问者可以访问相同的类型,并且同一访问者可以访问不同的类型。使用访问者模式执行的命名操作的效果可能取决于访问者和访问者(双重调度)。
显示双重调度的示例代码:
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