Как работает двойная отправка в шаблоне Visitor? - PullRequest
16 голосов
/ 20 июля 2011

Я изучал другие вопросы, связанные с шаблоном посетителя, но не мог понять реализацию двойной отправки в шаблоне посетителя.

Пожалуйста, обратитесь к ссылке Шаблон посетителя

Как работает двойная отправка в шаблоне Visitor?

Ответы [ 4 ]

37 голосов
/ 03 октября 2012

Однократная отправка

Single dispatch

Предположим, что Node является классом интерфейса, а два подкласса являются конкретными реализациями интерфейса.

Если вы вызываете метод GenerateCode() для экземпляра узла, фактическая выполняемая операция зависит от типа узла.Это может быть метод либо в VariableRefNode, либо в AssignmentNode.То же самое, если вы позвоните PrettyPrint().Таким образом, фактическое выполнение операции зависит от имени метода , который вы вызываете, и типа узла .

Double-dispatch

Nodes Visitors

На этот раз Node позволяет передавать параметр типа NodeVisitor в его метод, называемый Accept.В вашей программе, если вы вызываете Accept для экземпляра узла, фактическая выполняемая операция теперь зависит от типа узла (VariableRefNode или AssignmentNode) AND тип экземпляра посетителя, который вы передали в Accept (TypeCheckingVisitor или CodeGeneratingVisitor).

20 голосов
/ 20 июля 2011

Метод accept объекта элемента получает объект посетителя и вызывает метод visit объекта посетителя. Поскольку у объекта посетителя есть несколько visit методов, в зависимости от типа элемента вызывается соответствующий метод visit. Здесь у нас есть два вызова ( double dispatch ), которые задают элемент и правильную операцию для элемента (в зависимости от его типа).

7 голосов
/ 20 июля 2011

Ну, вот соответствующая цитата из этой статьи:

Посетитель осуществляет «двойную отправку». В ОО-сообщениях обычно указывается «единичная отправка» - выполняемая операция зависит от: имени запроса и типа получателя. В «двойной диспетчеризации» выполняемая операция зависит от: имени запроса и типа ДВУХ получателей (тип посетителя и тип посещаемого им элемента).

По сути, это означает, что разные посетители могут посещать один и тот же тип, а разные типы могут посещать один и тот же посетитель. Эффект именованной операции, выполняемой с использованием шаблона посетителя, может зависеть от посетителя и посещенного (двойная отправка).

0 голосов
/ 06 февраля 2019

Пример кода, который показывает двойную отправку:

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
...