Thema: Delphi Visitor Pattern

Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#9

AW: Visitor Pattern

  Alt 15. Jul 2010, 09:26
Wenn es aufgeteilt werden soll und sich dann nicht alle Klassen gegenseitig kennen können, dann muß man sich einfach auf eine gemeinsame Basis beschränken, welche sich kennt und wovon dann alles Andere/Unbekannte abgeleitet wird.

Ich denka mal das letze Beispiel dürfte eher dem Pattern entsprechen.
Da gibt es dann passende Visitor, die wissen was zu machen ist
und welche über einer gemeinsame Basis aufrufbar sind.

Delphi-Quellcode:
unit BaseUnit;

interface
  type
    Visitor = class;
    Base = class
    public
      procedure Accept(v : Visitor); virtual; abstract;
      function Visit(v : Visitor) : Integer; virtual; abstract;
    end;

    Visitor = class
    public
      procedure Visit(b : Base);
    end;

implementation

  { Visitor }
  procedure Visitor.Visit(b : Base);
  begin
    WriteLn(b.Visit(self));
  end;

  //...

end.

////////////////////////////////////

Schiff = class(Base)
public
  procedure Accept(v : Visitor); override;
  function Visit(v : Visitor) : Integer; override;
  // ...
  property Kabinen : Integer read Kabinenanzahl;
end;

function Schiff.Visit(v : Visitor) : Integer;
begin
  if v is Base then
    Result := Kabinen
  else
    ...
end;

Wobei man auch auf Seiten des Visitors aufsplitten könnte, aber das wäre dann weniger flexibel.
Delphi-Quellcode:
unit BaseUnit;

interface

  type
    Visitor = class;
    Base = class
    public
      procedure Accept(v : Visitor); virtual; abstract;
    end;

    StrBase = class(Base)
    public
      function StrVisit() : String; virtual; abstract;
    end;

    IntBase = class(Base)
    public
      function IntVisit() : Integer; virtual; abstract;
    end;

    Visitor = class
    public
      procedure Visit(b : Base);
    end;

implementation

  { Visitor }
  procedure Visitor.Visit(b: Base);
  begin
    if b is StrBase then
      WriteLn(b.StrVisit);
    else if b is IntBase then
      WriteLn(b.IntVisit);
  end;

  //...

end.
oder
Delphi-Quellcode:
unit BaseUnit;

interface

  type
    TVisitType = (vtInt, vtStr);
    Visitor = class;
    Base = class
    public
      procedure Accept(v : Visitor); virtual; abstract;
      funktion GetVisitType: TVisitType; virtual; abstract;
      function IntVisit() : Integer; virtual; {abstract;}
      function StrVisit() : String; virtual; {abstract;}
      // {...} vielleicht einen leeren Dummy verwenden,
      // damit man nicht überall alles überschreiben muß
    end;

    Visitor = class
    public
      procedure Visit(b : Base);
    end;

implementation

  { Visitor }
  procedure Visitor.Visit(b: Base);
  begin
    case b.GetVisitType of
      vtInt: WriteLn(b.IntVisit);
      vtStr: WriteLn(b.StrVisit);
      else ...
    end;
  end;

  //...

end.

Eventuell kannst du auch den Visitor aufteilen.
Da kennt dann jeder Visitornachfahre seine Base-Class und weiß was mit ihr zu machen ist.
Delphi-Quellcode:
unit BaseUnit;

interface
  type
    Visitor = class;
    Base = class
    public
      procedure Accept(v : Visitor); virtual; abstract;
      procedure Visit(v : Visitor); virtual; abstract;
    end;

    Visitor = class
    public
      procedure Visit(b : Base);
    end;

implementation

  { Visitor }
  procedure Visitor.Visit(b : Base);
  begin
    b.Visit(self);
  end;

  //...

end.

///////////////////////////////////////////////////////

unit StrBaseUnit;

interface
  uses
    BaseUnit;

  type
    StrBase = class()Base
    public
      procedure Accept(v : Visitor); override;
      procedure StrVisit; virtual; abstract;
    end;

    StrVisitor = class(Visitor)
    public
      procedure StrVisit(b : Base);
    end;

implementation

  { Visitor }
  procedure StrVisitor.StrVisit(b : Base);
  begin
    WriteLn((b as StrBase).StrVisit);
  end;

  //...

end.
$2B or not $2B

Geändert von himitsu (15. Jul 2010 um 09:35 Uhr)
  Mit Zitat antworten Zitat