AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Generisches Visitor-Pattern

Ein Thema von mael · begonnen am 11. Mär 2020 · letzter Beitrag vom 11. Mär 2020
Antwort Antwort
Benutzerbild von mael
mael

Registriert seit: 13. Jan 2005
391 Beiträge
 
Delphi XE3 Professional
 
#1

AW: Generisches Visitor-Pattern

  Alt 11. Mär 2020, 20:11
Das C# Beispiel betrachte ich mal als gutes Beispiel, wie man es nicht machen sollte. Nur weil C# davor steht, ist der Code ja nicht automatisch über jeden Zweifel erhaben.
Da hast du natürlich Recht. Ist halt die Version die ich üblicherweise kenne, bin aber gerne bereit was zu lernen.
Was ist denn der praktische Vorteil deiner Lösung, also was "So solltest die niemals t.Accept(Visitor) aufrufen, sondern immer Visitor.Visit(t)" angeht? Inwiefern entkoppelt es mehr da man sich ja in beiden Fällen auf eine abstrakte Klasse/Interface bezieht?

Zitat:
Mein Minimalbeispiel kann man natürlich so umschreiben, (auch wenn Interfaces jetzt unter Delphi nicht sehr praktisch sind) das ist schon klar.
Nun, ich kann nur kommentieren, was ich sehe. Da ich deine realen Anforderungen nicht kenne, kann ich dazu auch keine Vorschläge machen.
Schwer das mit wenig Code zu illustrieren. Ein Beispiel wäre das "pretty printing" eines Syntaxbaums (AST). Hierzu muss man das Einrückungslevel mitliefern, bzw. einen Präfixstring, der je nach Knoten anders ist, an die Kindknoten weiterreichen.

Hier gibt es ähnliche Fragen:
https://stackoverflow.com/questions/...h-return-value
https://stackoverflow.com/questions/...isitor-pattern

Zitat:
Aber das Ziel ist es das Visitorpattern so zu erweitern, dass man zusätzliche Parameter/Rückgabewerte haben kann.
Das Ziel geht meiner Meinung nach konträr zum ursprünglichen Anliegen des Visitor Patterns - der Entkopplung der Strukturklassen und deren Verarbeitung. Ist aber eben auch nur meine Meinung.
Deswegen will ich die Parameter ja allgemein halten.

Im Endeffekt sollte etwas wie die Lösung für Format() gut funktionieren:
procedure Accept(Visitor: TVisitor; const Args: array of const); Den Rückgabewert könnte man dann über eine Instanz-Variable des Visitors lösen, wie in deinem Vorschlag, und auch in dem C++-Beispiel oben. Im Endeffekt ist das dann eine Art Callbackfunktion (die ja auch häufig zusätzliche "User"-Parameter haben).

Damit wäre ich eigentlich zufrieden. Bleibt die obige Frage übrig.
HxD, schneller Hexeditor:
http://mh-nexus.de/hxd

Geändert von mael (11. Mär 2020 um 20:21 Uhr)
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.277 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Generisches Visitor-Pattern

  Alt 11. Mär 2020, 20:20
Hallo,
ohne mich jetzt mit dem Code tief beschäftigt zu haben

Zitat:
zusätzliche Parameter/Rückgabewerte
Hilft es, mit einer generischen, oder abstrakten Parameterklasse zu arbeiten?
Heiko
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.771 Beiträge
 
Delphi 12 Athens
 
#3

AW: Generisches Visitor-Pattern

  Alt 11. Mär 2020, 21:55
Inwiefern entkoppelt es mehr da man sich ja in beiden Fällen auf eine abstrakte Klasse/Interface bezieht?
Weil dann der Visitor entscheidet, wann und wie er das Accept aufruft. Er könnte das auch einem anderen Visitor überlassen, den er temporär erstellt und dann den Node an dessen Visit weitergibt. Das hatte ich mir auch schon überlegt, um die unterschiedlichen Separatoren (sLineBreak und ', ') zu abstrahieren.

Zitat:
Hierzu muss man das Einrückungslevel mitliefern, bzw. einen Präfixstring, der je nach Knoten anders ist, an die Kindknoten weiterreichen.
Das lässt sich aber ganz hervorragend innerhalb der Visitorklasse regeln. Der Knoten soll sich ja um sowas gar nicht kümmern. Der muss nur die nötigen Properties bereitstellen.

Hier (wieder) mal ein schnelles Beispiel basierend auf dem vorigen Code (Create, Destroy und GetResultValue entsprechen TContentVisitor). Es wird einfach die Baumstruktur mit entsprechenden Einrückungen und Präfix dargestellt. Dabei werden die Node-Typen unterschiedlich formatiert. Man sieht hier auch deutlich den Vorteil der virtuellen Visit Methode gegenüber einem Aufruf von Accept:
Delphi-Quellcode:
type
  TIndentVisitor = class(TNodeVisitor)
  private
    FLevel: Integer;
    FList: TStringList;
    FPrefix: string;
    function GetResultValue: string;
  protected
    procedure VisitNodeA(Node: TNodeA); override;
    procedure VisitNodeB(Node: TNodeB); override;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Visit(ANode: TNode); override;
    property ResultValue: string read GetResultValue;
  end;
Delphi-Quellcode:
procedure TIndentVisitor.Visit(ANode: TNode);
var
  i: Integer;
  savePrefix: string;
begin
  savePrefix := FPrefix;
  inherited; // hier wird implizit das Accept aufgerufen, was auf die jeweilige VisitNodeA/B Methode verzweigt
  FList.Add(StringOfChar(' ', 2*FLevel) + FPrefix);
  Inc(FLevel);
  for i := 0 to ANode.ChildCount - 1 do
  begin
    Visit(ANode.Children[i]);
  end;
  Dec(FLevel);
  FPrefix := savePrefix;
end;

procedure TIndentVisitor.VisitNodeA(Node: TNodeA);
begin
  FPrefix := FPrefix + '.' + Node.ClassName;
end;

procedure TIndentVisitor.VisitNodeB(Node: TNodeB);
begin
  FPrefix := FPrefix + '.[' + Node.ClassName + ']';
end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz