Delphi Enterprise:如何在没有循环引用的情况下应用访问者模式? [英] Delphi Enterprise: how can I apply the Visitor Pattern without circular references?
问题描述
使用 Delphi 2009 Enterprise,我在模型视图中为 GoF 访问者模式创建了代码,并将代码分成两个单元:一个用于域模型类,一个用于访问者(因为我可能需要其他单元用于不同的访问者实现,所有内容都在一个单元中?'大泥球'前面!)
With Delphi 2009 Enterprise I created code for the GoF Visitor Pattern in the model view, and separated the code in two units: one for the domain model classes, one for the visitor (because I might need other units for different visitor implementations, everything in one unit? 'Big ball of mud' ahead!).
unit VisitorUnit;
interface
uses
ConcreteElementUnit;
type
IVisitor = interface;
IElement = interface
procedure Accept(AVisitor :IVisitor);
end;
IVisitor = interface
procedure VisitTConcreteElement(AElement :TConcreteElement);
end;
TConcreteVisitor = class(TInterfacedObject, IVisitor)
public
procedure VisitTConcreteElement(AElement :TConcreteElement);
end;
implementation
procedure TConcreteVisitor.VisitTConcreteElement(AElement :TConcreteElement);
begin
{ provide implementation here }
end;
end.
以及商业模式课程的第二单元
and the second unit for the business model classes
unit ConcreteElementUnit;
interface
uses
VisitorUnit;
type
TConcreteElement = class(TInterfacedObject, IElement)
public
procedure Accept(AVisitor :IVisitor); virtual;
end;
Class1 = class(TConcreteElement)
public
procedure Accept(AVisitor :IVisitor);
end;
implementation
{ Class1 }
procedure Class1.Accept(AVisitor: IVisitor);
begin
AVisitor.VisitTConcreteElement(Self);
end;
end.
看到问题了吗?循环单位参考.有没有优雅的解决方案?我想它需要n+1"个带有基接口/基类定义的附加单元来避免 CR 问题,以及像硬转换这样的技巧?
See the problem? A circular unit reference. Is there an elegant solution? I guess it requires "n+1" additional units with base interface / base class definitions to avoid the CR problem, and tricks like hard casts?
推荐答案
我使用以下方案来实现灵活的访问者模式:
I use the following scheme to implement a flexible visitor pattern:
unit uVisitorTypes;
type
IVisited = interface
{ GUID }
procedure Accept(Visitor: IInterface);
end;
IVisitor = interface
{ GUID }
procedure Visit(Instance: IInterface);
end;
TVisitor = class(..., IVisitor)
procedure Visit(Instance: IInterface);
end;
procedure TVisitor.Visit(Instance: IInterface);
var
visited: IVisited;
begin
if Supports(Instance, IVisited, visited) then
visited.Accept(Self)
else
// raise exception or handle error elsewise
end;
元素类的单位
unit uElement;
type
TElement = class(..., IVisited)
procedure Accept(Visitor: IInterface);
end;
// declare the visitor interface next to the class-to-be-visited declaration
IElementVisitor = interface
{ GUID }
procedure VisitElement(Instance: TElement);
end;
procedure TElement.Accept(Visitor: IInterface);
var
elementVisitor: IElementVisitor;
begin
if Supports(Visitor, IElementVisitor, elementVisitor) then
elementVisitor.VisitElement(Self)
else
// if override call inherited, handle error or simply ignore
end;
实际访问者实现
unit MyVisitorImpl;
uses
uVisitorTypes, uElement;
type
TMyVisitor = class(TVisitor, IElementVisitor)
procedure VisitElement(Instance: TElement);
end;
procedure TMyVisitor.VisitElement(Instance: TElement);
begin
// Do whatever you want with Instance
end;
呼叫访客
uses
uElement, uMyElementVisitor;
var
visitor: TMyVisitor;
element: TElement;
begin
// get hands on some element
visitor := TMyVisitor.Create;
try
visitor.Visit(element);
finally
visitor.Free;
end;
end;
这篇关于Delphi Enterprise:如何在没有循环引用的情况下应用访问者模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!