加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi Enterprise:如何在没有循环引用的情况下应用访问者模式

发布时间:2020-12-15 09:23:55 所属栏目:大数据 来源:网络整理
导读:使用Delphi 2009 Enterprise,我在模型视图中为GoF访客模式创建了代码,并将代码分为两个单元:一个用于域模型类,一个用于访问者(因为我可能需要其他单元用于不同的访问者实现,所有内容都在一个单位?’ Big ball of mud‘提前!). unit VisitorUnit;interface
使用Delphi 2009 Enterprise,我在模型视图中为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.

和业务模型类的第二个单元

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问题,并像硬铸造一样的技巧?

解决方法

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

基本访客类型的声明

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;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读