Простой пример шаблона визитер. Когда нужно вставить новую функциональность, не меняя класса.
unit uVisitor;
interface
uses
SysUtils, System.Generics.Collections;
type
TElement = class
private
FName: string;
public
constructor Create(aName: string);
property Name: string read FName;
end;
TVisitor = class
public
procedure VisitElement(aElement: TElement); virtual; abstract;
end;
TConcreteVisitor = class(TVisitor)
public
procedure VisitElement(aElement: TElement); override;
end;
TObjectStructure = class
private
FObjectList: TObjectList<TElement>;
public
constructor Create();
destructor Destroy; override;
procedure Add(aElement: TElement);
procedure Accept(aVisitor: TVisitor);
end;
implementation
uses
uMain;
{ TConcreteVisitor }
procedure TConcreteVisitor.VisitElement(aElement: TElement);
begin
Main.mMemo.Lines.Add(Format('Name of element is %s', [aElement.Name]));
end;
{ TElement }
constructor TElement.Create(aName: string);
begin
FName := aName;
end;
{ TObjectStructure }
procedure TObjectStructure.Accept(aVisitor: TVisitor);
var
element: TElement;
begin
for element in FObjectList do
aVisitor.VisitElement(element);
end;
procedure TObjectStructure.Add(aElement: TElement);
begin
FObjectList.Add(aElement);
end;
constructor TObjectStructure.Create;
begin
FObjectList := TObjectList<TElement>.Create(true);
end;
destructor TObjectStructure.Destroy;
begin
FObjectList.Free();
inherited;
end;
end.
И теперь попробуем, что у нас получилось
procedure TMain.FormCreate(Sender: TObject);
var
os: TObjectStructure;
begin
os := TObjectStructure.Create();
try
os.Add(TElement.Create('Stas'));
os.Add(TElement.Create('Helen'));
os.Accept(TConcreteVisitor.Create());
finally
os.Free();
end;
end;
Также, интересная статья на хабре
Или так…
unit uVisitor;
interface
uses
SysUtils, System.Generics.Collections;
type
TVisitor = class;
TElement = class
private
FName: string;
public
constructor Create(aName: string);
property Name: string read FName;
procedure Accept(aVisitor: TVisitor); virtual; abstract;
end;
TConcreteElement = class(TElement)
public
procedure Accept(aVisitor: TVisitor); override;
end;
TVisitor = class
public
procedure VisitElement(aElement: TElement); virtual; abstract;
end;
TConcreteVisitor = class(TVisitor)
public
procedure VisitElement(aElement: TElement); override;
end;
TObjectStructure = class
private
FObjectList: TObjectList<TElement>;
public
constructor Create();
destructor Destroy; override;
procedure Add(aElement: TElement);
procedure Accept(aVisitor: TVisitor);
end;
implementation
uses
uMain;
{ TConcreteVisitor }
procedure TConcreteVisitor.VisitElement(aElement: TElement);
begin
Main.mMemo.Lines.Add(Format('Name of element is %s', [aElement.Name]));
end;
{ TElement }
constructor TElement.Create(aName: string);
begin
FName := aName;
end;
{ TObjectStructure }
procedure TObjectStructure.Accept(aVisitor: TVisitor);
var
element: TElement;
begin
for element in FObjectList do
element.Accept(aVisitor);
// aVisitor.VisitElement(element);
end;
procedure TObjectStructure.Add(aElement: TElement);
begin
FObjectList.Add(aElement);
end;
constructor TObjectStructure.Create;
begin
FObjectList := TObjectList<TElement>.Create(true);
end;
destructor TObjectStructure.Destroy;
begin
FObjectList.Free();
inherited;
end;
{ TConcreteElement }
procedure TConcreteElement.Accept(aVisitor: TVisitor);
begin
aVisitor.VisitElement(Self);
end;
end.