gpt4 book ai didi

德尔福企业版 : how can I apply the Visitor Pattern without circular references?

转载 作者:行者123 更新时间:2023-12-03 15:26:10 26 4
gpt4 key购买 nike

使用 Delphi 2009 Enterprise,我在模型 View 中为 GoF 访问者模式创建了代码,并将代码分为两个单元:一个用于域模型类,一个用于访问者(因为我可能需要其他单元来实现不同的访问者实现) ,一切都在一个单元中?“Big ball of mud”!)。

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.

第二单元是商业模式类(class)

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”个具有基接口(interface)/基类定义的附加单元来避免 CR 问题,以及诸如硬转换之类的技巧?

最佳答案

我使用以下方案来实现灵活的访问者模式:

基本访问者类型声明

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;

关于德尔福企业版 : how can I apply the Visitor Pattern without circular references?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2356318/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com