Я изучал другие вопросы, связанные с шаблоном посетителя, но не мог понять реализацию двойной отправки в шаблоне посетителя.
Перейдите по ссылке Шаблон посетителя.
Как работает двойная отправка в шаблоне «Посетитель»?
Я изучал другие вопросы, связанные с шаблоном посетителя, но не мог понять реализацию двойной отправки в шаблоне посетителя.
Перейдите по ссылке Шаблон посетителя.
Как работает двойная отправка в шаблоне «Посетитель»?
Метод accept
объекта элемента получает объект посетителя и вызывает метод visit
для объекта посетителя. Поскольку объект посетителя имеет несколько методов visit
, в зависимости от типа элемента вызывается соответствующий метод visit
. Здесь у нас есть два вызова (двойная отправка), которые определяют элемент и правильную операцию для элемента (в зависимости от его типа).
Однократное отправление
Предположим, что Node — это класс интерфейса, а два подкласса — конкретные реализации интерфейса.
Если вы вызываете метод GenerateCode()
для экземпляра узла, фактическая выполняемая операция зависит от типа узла. Это может быть метод либо в VariableRefNode
, либо в AssignmentNode
. То же самое, если вы позвоните PrettyPrint()
. Таким образом, фактическое выполнение операции зависит от имени метода, который вы вызываете, и типа узла.
Двойная отправка
На этот раз Node
позволяет вам передать параметр типа NodeVisitor
в его метод с именем Accept
. В вашей программе, если вы вызываете Accept
для экземпляра узла, фактическая выполняемая операция теперь зависит от типа узла (VariableRefNode
или AssignmentNode
) И типа посетителя. экземпляр, который вы передали в Accept
(TypeCheckingVisitor
или CodeGeneratingVisitor
).
Ну и соответствующая цитата из этой статьи:
Посетитель реализует «двойную отправку». Сообщения 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