Vorteil des Entwurfsmusters Besucher/Visitor?

Status
Nicht offen für weitere Antworten.

deamon

Bekanntes Mitglied
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:

Code:
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

Top Contributor
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:
Code:
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

Bekanntes Mitglied
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

Bekanntes Mitglied
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

Top Contributor
Nur über Sichtbarkeit oder Hacks. Wenn es bei dir über die Sichbarkeit nicht machbar ist, dann spar dir die Hacks ;)
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen

Ähnliche Java Themen

Neue Themen


Oben