【问题标题】:How does double dispatch work in Visitor pattern?访客模式中的双重调度如何工作?
【发布时间】:2011-07-20 12:54:12
【问题描述】:

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

请参考链接 Visitor Pattern

访客模式中的双重调度如何工作?

【问题讨论】:

  • 你不明白的地方能不能具体点?
  • 恕我直言,您应该考虑在运行时而不是编译时将分派作为函数重载。

标签: java design-patterns visitor-pattern double-dispatch


【解决方案1】:

单发

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

如果您在节点实例上调用GenerateCode() 方法,实际执行的操作取决于节点的类型。它可以是VariableRefNodeAssignmentNode 中的方法。拨打PrettyPrint()也是一样。因此,实际执行的操作取决于您正在调用的方法的名称节点的类型

双发

这次Node 允许您将NodeVisitor 类型的参数传递给它的名为Accept 的方法。在您的程序中,如果您在节点实例上调用Accept,现在执行的实际操作取决于节点的类型VariableRefNodeAssignmentNodeAND 您传递给Accept 的访问者实例的类型(TypeCheckingVisitorCodeGeneratingVisitor)。

【讨论】:

    【解决方案2】:

    元素对象的accept 方法接收一个访问者对象,并在访问者对象上调用visit 方法。由于访问者对象有多个visit 方法,因此根据元素类型调用适当的visit 方法。这里我们有两个调用(double dispatch)来指定元素的元素和正确的操作(基于它的类型)。

    【讨论】:

      【解决方案3】:

      嗯,这是那篇文章的相关引述:

      Visitor 实现了“双重调度”。 OO 消息通常表现为“单次调度”——执行的操作取决于:请求的名称和接收者的类型。在“双重调度”中,执行的操作取决于:请求的名称,以及两个接收者的类型(访问者的类型和它访问的元素的类型)。

      这实质上意味着不同的访问者可以访问相同的类型,并且同一访问者可以访问不同的类型。使用访问者模式执行的命名操作的效果可能取决于访问者访问者(双重调度)。

      【讨论】:

        【解决方案4】:

        显示双重调度的示例代码:

        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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-02
          • 2012-12-13
          • 2012-03-09
          • 1970-01-01
          • 1970-01-01
          • 2010-09-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多