Ethan Yager 0 Posted June 19, 2019 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
Remy Lebeau 1394 Posted June 19, 2019 (edited) 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 June 19, 2019 by Remy Lebeau Share this post Link to post
A.M. Hoornweg 144 Posted June 23, 2019 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