Jump to content
Ethan Yager

Visitor Pattern implemenation

Recommended Posts

I can't seem to implement the visitor pattern in Delphi without circular references. Does anyone know of a way to implement the visitor pattern without having all of the classes in one big unit? For instance, if I have a complex tree structure (psuedo code so that I can demonstrate concisely):

 

Unit Base

type

TBase = class

end;

-------------------------------------------------------

Unit Bolt

uses Base;

TBolt = class(TBase)

  procedure Tighten;

  procedure Untighten;

 

  Visit(visitor: TAutomobileVisitor); <-- Requires circular reference to Automobile unit 

end;

-------------------------------------------------------

Unit Door

uses Base, Bolt;

type

TDoor = class(TBase)

  Bolts: array of TBolt;

  procedure Open;

  procedure Close;

 

  Visit(visitor: TAutomobileVisitor);  <-- Requires circular reference to Automobile unit

end;

-------------------------------------------------------

Unit Seat

uses Base, Bolt;

type

TSeat = class(TBase)

  Bolts: array of TBolt;

  procedure Heat(on: boolean);

 

  Visit(visitor: TAutomobileVisitor);  <-- Requires circular reference to Automobile unit

end;

-------------------------------------------------------

Unit Automobile

uses Base, Door, Seat, Bolt;

type

TAutomobile = class(TBase)

  FOwnerName: string;

  Doors: array of TDoor;

  Seats: array of TSeat;

 

  Visit(visitor: TAutomobileVisitor); 

end;

 

TAutomobileVisitor = class

  procedure Visit(o: TAutomobile); overload; virtual;

  procedure Visit(o: TBolt); overload; virtual;

  procedure Visit(o: TDoor); overload; virtual;

  procedure Visit(o: TSeat); overload; virtual;

end;

-------------------------------------------------------

 

I have tried moving things around and using interfaces but can't seem to avoid circular references.

 

Share this post


Link to post

See Uwe Raabe's blog articles about the Visitor Pattern in Delphi:

 

Part 1

Part 2

Part 3

Part 4

 

He shows how to work around the circular referencing issue using interfaces and multiple units.

Edited by Remy Lebeau

Share this post


Link to post

Use interfaces & tInterfacedObject.

 

Put the interfaces like iVisitor, iDoor, iAutomobile etc in a common unit that contains no implementation code at all.  The implementations+class factories should be in entirely different units that don't reference each other at all. 

 

Oh and instead of writing a big bunch of overloaded Visit() methods in a class, you could consider using a single method and use the "is" or the "supports" keyword if you really need to know the type of visitor.

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×