Visitor pattern. Simple example

Простой пример шаблона визитер. Когда нужно вставить новую функциональность, не меняя класса.

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.
This entry was posted in Без рубрики. Bookmark the permalink.