java - patrones - visitor pattern
¿Cómo funciona el doble despacho en el patrón de visitante? (4)
Bueno, aquí está la cita relevante de ese artículo:
El visitante implementa el "doble despacho". Los mensajes OO manifiestan rutinariamente un "envío único": la operación que se ejecuta depende de: el nombre de la solicitud y el tipo de receptor. En “doble despacho”, la operación ejecutada depende de: el nombre de la solicitud y el tipo de DOS receptores (el tipo de Visitante y el tipo de elemento que visita).
Básicamente, esto significa que diferentes visitantes pueden visitar el mismo tipo y diferentes tipos pueden ser visitados por el mismo visitante. El efecto de una operación con nombre que se realiza utilizando el patrón de visitante puede depender del visitante y del visitado (doble envío).
Estaba estudiando otras preguntas relacionadas con el patrón de visitantes, pero no podía entender la implementación del doble despacho en el patrón de visitantes.
Por favor, consulte el enlace Patrón de visitante
¿Cómo funciona el doble despacho en el patrón de visitante?
Un código de ejemplo, que muestra doble despacho:
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);
}
}
La salida es:
Node visitor 1, node Node A
Node visitor 2, node Node A
Node visitor 1, node Node B
Node visitor 2, node Node B
Un solo despacho
Supongamos que Node es una clase de interfaz y las dos subclases son implementaciones concretas de la interfaz.
Si llama al método GenerateCode()
en una instancia de nodo, la operación real que se ejecuta depende del tipo de nodo. Podría ser el método en VariableRefNode
o AssignmentNode
. Es lo mismo si llamas a PrettyPrint()
. Por lo tanto, la operación real que se ejecuta depende del nombre del método que está llamando y del tipo de nodo .
Doble despacho
Esta vez, el Node
le permite pasar un parámetro de tipo NodeVisitor
a su método llamado Accept
. En su programa, si llama Accept
en una instancia de nodo, la operación real que se ejecuta ahora depende del tipo de nodo ( VariableRefNode
o AssignmentNode
) Y del tipo de la instancia de visitante que TypeCheckingVisitor
en Accept
( TypeCheckingVisitor
o CodeGeneratingVisitor
).
El método de accept
del objeto del elemento recibe un objeto visitante y llama al método de visit
en el objeto visitante. Como el objeto visitante tiene varios métodos de visit
, en función del tipo de elemento se llama al método de visit
apropiado. Aquí tenemos dos llamadas ( doble despacho ) que especifican el elemento y la operación correcta para el elemento (según su tipo).