Einzelnen Beitrag anzeigen

Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Generisches Visitor-Pattern

  Alt 11. Mär 2020, 22: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