示例:访问者接口
说明:
(1)、定义
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
(2)、结构
访问者
Visitor(访问者):为该对象结构中ConcreteElement的每一个类声明一个Visit操作。该操作的名字和特征标识了发送Visit请求给该访问者的那个类。这使得访问者可以确定正被访问元素的具体的类。这样访问者就可以通过该元素的特定接口直接访问它。
ConcreteVisitor(具体访问者):实现每个由Visitor声明的操作。每个操作实现本算法的一部分,而该算法片断乃是对应于结构中对象的类。ConcreteVisitor为该算法提供了上下文并存储它的局部状态。这一状态常常在遍历该结构的过程中累积结果。
对象
Element(元素):定义一个Accept操作,它以一个访问者为参数。
ConcreteElement(具体元素):实现Accept操作,该操作以一个访问者为参数。
ObjectStructure(对象结构):能枚举它的元素。可以提供一个高层的接口以允许该访问者访问它的元素。可以是一个复合(参见Composite)或是一个集合,如一个列表或一个无序集合。
代码:
unit uVisitor;
interface
uses
Dialogs, Contnrs;
type
TVisitor = class;
TElement = class
public
procedure Accept(AVisitor: TVisitor); virtual; abstract;
end;
TConcreteElementA = class(TElement)
public
procedure Accept(AVisitor: TVisitor); override;
procedure OperationA;
end;
TConcreteElementB = class(TElement)
public
procedure Accept(AVisitor: TVisitor); override;
procedure OperationB;
end;
TObjectStructure = class(TObjectList)
private
function GetItems(Index: Integer): TElement;
public
procedure Accept(AVisitor: TVisitor);
//---
property Items[Index: Integer]: TElement read GetItems;
end;
TVisitor = class
public
procedure VisitConcreteElementA(AElement: TConcreteElementA); virtual; abstract;
procedure VisitConcreteElementB(AElement: TConcreteElementB); virtual; abstract;
end;
TConcreteVisitor1 = class(TVisitor)
public
procedure VisitConcreteElementA(AElement: TConcreteElementA); override;
procedure VisitConcreteElementB(AElement: TConcreteElementB); override;
end;
TConcreteVisitor2 = class(TVisitor)
public
procedure VisitConcreteElementA(AElement: TConcreteElementA); override;
procedure VisitConcreteElementB(AElement: TConcreteElementB); override;
end;
procedure Test;
implementation
procedure Test;
var
AStructure: TObjectStructure;
AVisitor: TVisitor;
begin
AStructure := TObjectStructure.Create;
AVisitor := TConcreteVisitor1.Create;
try
with AStructure do
begin
Add(TConcreteElementA.Create);
Add(TConcreteElementB.Create);
//---
Accept(AVisitor);
end;
finally
AVisitor.Free;
AStructure.Free;
end;
end;
procedure TConcreteElementA.Accept(AVisitor: TVisitor);
begin
AVisitor.VisitConcreteElementA(Self);
end;
procedure TConcreteElementA.OperationA;
begin
ShowMessage('A');
end;
procedure TConcreteElementB.Accept(AVisitor: TVisitor);
begin
AVisitor.VisitConcreteElementB(Self);
end;
procedure TConcreteElementB.OperationB;
begin
ShowMessage('B');
end;
procedure TConcreteVisitor1.VisitConcreteElementA(AElement: TConcreteElementA);
begin
AElement.OperationA;
end;
procedure TConcreteVisitor1.VisitConcreteElementB(AElement: TConcreteElementB);
begin
AElement.OperationB;
end;
procedure TConcreteVisitor2.VisitConcreteElementA(AElement: TConcreteElementA);
begin
AElement.OperationA;
AElement.OperationA;
end;
procedure TConcreteVisitor2.VisitConcreteElementB(AElement: TConcreteElementB);
begin
AElement.OperationB;
AElement.OperationB;
end;
procedure TObjectStructure.Accept(AVisitor: TVisitor);
var
i: Integer;
begin
for i := 0 to Self.Count - 1 do
Self.Items[i].Accept(AVisitor);
end;
function TObjectStructure.GetItems(Index: Integer): TElement;
begin
Result := TElement(inherited Items[Index]);
end;
end.