Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在访客模式中,双重分派是如何工作的?_Java_Design Patterns_Visitor Pattern_Double Dispatch - Fatal编程技术网

Java 在访客模式中,双重分派是如何工作的?

Java 在访客模式中,双重分派是如何工作的?,java,design-patterns,visitor-pattern,double-dispatch,Java,Design Patterns,Visitor Pattern,Double Dispatch,我正在研究与访问者模式相关的其他问题,但无法理解访问者模式中双重分派的实现 请参考链接 在访客模式中,双重分派是如何工作的?好吧,下面是那篇文章的相关引用: 访客执行“双重分派”。OO消息通常表现为“单一分派”——执行的操作取决于:请求的名称和接收方的类型。在“双重分派”中,执行的操作取决于:请求的名称和两个接收者的类型(访问者的类型和它访问的元素的类型) 这本质上意味着不同的访问者可以访问同一类型,同一访问者可以访问不同类型。使用访问者模式执行的命名操作的效果可能取决于访问者和已访问的(双重

我正在研究与访问者模式相关的其他问题,但无法理解访问者模式中双重分派的实现

请参考链接


在访客模式中,双重分派是如何工作的?

好吧,下面是那篇文章的相关引用:

访客执行“双重分派”。OO消息通常表现为“单一分派”——执行的操作取决于:请求的名称和接收方的类型。在“双重分派”中,执行的操作取决于:请求的名称和两个接收者的类型(访问者的类型和它访问的元素的类型)


这本质上意味着不同的访问者可以访问同一类型,同一访问者可以访问不同类型。使用访问者模式执行的命名操作的效果可能取决于访问者和已访问的(双重分派)。

元素对象的
accept
方法接收访问者对象,并对访问者对象调用
visit
方法。由于访问者对象有几个
visit
方法,因此根据元素类型调用相应的
visit
方法。这里我们有两个调用(双重分派),用于指定元素和元素的正确操作(基于其类型)

单一分派

假设Node是一个接口类,两个子类是接口的具体实现

如果对节点实例调用
GenerateCode()
方法,实际执行的操作取决于节点的类型。它可以是
VariableRefNode
AssignmentNode
中的方法。如果调用
PrettyPrint()
,也是一样的。因此,实际执行的操作取决于所调用方法的名称和节点的类型

双重分派


这一次,
节点
允许您将类型为
NodeVisitor
的参数传递给其名为
Accept
的方法。在程序中,如果对节点实例调用
Accept
,现在执行的实际操作取决于节点的类型(
VariableRefNode
AssignmentNode
Accept
TypeCheckingVisitor
CodeGeneratingVisitor
)。

一个示例代码,显示双重分派:

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