Thema: Delphi Visitor Pattern

Einzelnen Beitrag anzeigen

Benutzerbild von Uwe Raabe
Uwe Raabe

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

AW: Visitor Pattern

  Alt 15. Jul 2010, 11:16
das IBaseVisitor Interface kann ich mir bei einer abstrakten Basisklasse schenken, da es keine Base Instanzen gibt, korrekt
Das hängt davon ab, was dein Visitor tun soll. So könnte ein Visitor, der lediglich auf TBase-Eigenschaften und Methoden zugreift, auch nur das IBaseVisitor-Interface implementieren und die IAVisitor- und IBVisitor-Interfaces gar nicht implementieren. Ergänzend dazu muss man dann allerdings die Implementationen von Accept in TA und TB leicht abwandeln.

Delphi-Quellcode:
procedure TA.Accept(Visitor: IVisitor);
var
  MyVisitor: IAVisitor;
begin
  if Supports(Visitor, IAVisitor, MyVisitor) then
    MyVisitor.VisitA(Self)
  else
    inherited;
end;
Delphi-Quellcode:
procedure TB.Accept(Visitor: IVisitor);
var
  MyVisitor: IBVisitor;
begin
  if Supports(Visitor, IBVisitor, MyVisitor) then
    MyVisitor.VisitB(Self)
  else
    inherited;
end;
Wenn nun der Visitor das passende Interface nicht implementiert, wird einfach die Accept-Methode des Vorfahren aufgerufen.

Delphi-Quellcode:
unit uBaseVisitor;

interface

uses
  Classes, uVisitorTypes, uBase;

type
  TBaseVisitor = class(TInterfacedObject, IVisitor, IBaseVisitor)
  protected
    procedure NotSupported(const Name: string);
    procedure VisitBase(Instance: TBase);
  public
    procedure Visit(Instance: IInterface);
  end;

implementation

uses
  SysUtils;

procedure TBaseVisitor.NotSupported(const Name: string);
begin
  // nach Bedarf ignorieren oder Fehler melden
end;

procedure TBaseVisitor.Visit(Instance: IInterface);
var
  visited: IVisited;
begin
  if Supports(Instance, IVisited, visited) then
    visited.Accept(Self)
  else
    // nach Bedarf ignorieren oder Fehler melden
end;

procedure TBaseVisitor.VisitBase(Instance: TBase);
begin
  // tue was mit Instance, was jedes TBase kann
end;

end.


TVisitor.VisitA(Instance: TA);
TVisitor.VisitB(Instance: TB);

würde ich wohl abstrakt machen und konkrete Besucher von TVisitor ableiten. Das wäre dann im Stil 'Template Methode'. Dieser Supports / Not Supported Kram wird von der Basisklasse behandelt, der konkrete Besucher kümmert sich nur noch um A und B.
Das hängt natürlich auch von deinem konkreten Fall ab. In meinen Anwendungen habe ich sowohl Visitors, die von einem Basis-Visitor abgeleitet sind, als auch solche, die von Grund auf neu implementiert werden.

Wenn irgendeine Struktur (Liste, Baum, ...) von TBase-Abkömmligen vorliegt, könnte man einen Visitor schreiben, der die Struktur iteriert und alle Instanzen zählt. Der bräcuhte dann nur IBaseVisitor implementieren.

Es gibt da keine allgemeingültige Vorgehensweise - wie so oft in unserer Branche...

Ich hatte mal vor, über das Thema "Visitor - eine praktikable Implementierung" einen Artikel zu schreiben, in dem die obige Implentierung erläutert und verschiedene Szenarien durchgespielt werden, aber es kommt halt immer etwas dazwischen.

Wär' ja vielleicht auch was für die Delphi-Tage???
Uwe Raabe
  Mit Zitat antworten Zitat