# Vorteil des Entwurfsmusters Besucher/Visitor?



## deamon (14. Mrz 2009)

Hallo,

ich entwickle gerade einen Parser der einen abstrakten Syntaxbaum erzeugt. Die Elemente dieses Baums sollen dann auf unterschiedliche Weise dargestellt werden können. Meine derzeitige Implementierung sieht für diesen Zweck das Entwurfsmuster Besucher/Visitor vor. 

Das sieht dann etwa so aus:


```
public abstract class Visitor
{
  public abstract void render(ElementA a);
  public abstract void render(ElementB b);
}

public class VisitorHtml
{
  public void render(ElementA a)
  {
    System.out.println("A");
  }
  public void render(ElementB b)
  {
    System.out.println("B");
  }
}

public abstract class Element
{
  public abstract void accept(Visitor visitor);
}

public class ElementA extends Element
{
  public void accept(Visitor visitor)
  {
    visitor.render(this); // warum sollte das hier aufgerufen werden?
  }
}
```

Nun stellt sich mir die Frage, warum eine Besuchte Klasse eine Methode des Visitors (visitor.render(this)) aufrufen sollte. Es muss ja ohnehin jedes Element von außen angefasst werden, um den Visitor zu übergeben. Statt also elementxy.accept(visitor) aufzurufen, woraufhin das elementxy sich selbst dem Visitor übergibt, könnte man doch auch gleich visitor.render(elementxy) schreiben, oder mache ich gerade einen Denkfehler?


----------



## Wildcard (14. Mrz 2009)

Java ist eine Single Dispatch Sprache.
Angenommen du hast B extends A und eine Methode render(A a) und render(B b).
Die eine gibt a aus, die andere b.
Rufst du nun folgendes auf:
[HIGHLIGHT="Java"]A a = new A();
something.render(a);
B b = new B();
something.render(b);
A b1 = new B();
something.render(b1);[/HIGHLIGHT]
Deine Ausgabe ist nun:

```
a
b
a
```
Es wird also die Methode verlinkt, die zum Typ passt, die dem Compiler bekannt ist und im falle von b1, ist das render(A a).
Du müsstest also ein großes instanceof Konstrukt bauen und immer casten wenn du das nicht über einen Visitor realisierst.


----------



## deamon (15. Mrz 2009)

Danke für die Erklärung. Ich hatte nicht daran gedacht, dass ich in meiner Baumstruktur alle Referenzen auf die Kinder eines Elements den Typ des Wurzelelements haben. Ohne instanceof und casting hätte ich also immer nur das Wurzelelement gerendert.


----------



## deamon (16. Mrz 2009)

Gibt es eine Möglichkeit, den direkten Aufruf von visitor.render(something); außerhalb der accept-Methode zu unterbinden? Es wäre schön, wenn man andere Entwickler gleich von diesem Fehler abhalten könnte.


----------



## Wildcard (16. Mrz 2009)

Nur über Sichtbarkeit oder Hacks. Wenn es bei dir über die Sichbarkeit nicht machbar ist, dann spar dir die Hacks


----------

