strategy pattern patrones patron explicacion diseño java design-patterns visitor-pattern double-dispatch

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