We can now derive from TShapeVisitor to achieve the different behaviour. For instance, to draw on a TCanvas we would have something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
unit uCanvasVisitorGoF; interface uses uVisitorGoF, Graphics, Types; type TShapeVisitorCanvas = class(TShapeVisitor) private FCanvas: TCanvas; property Canvas: TCanvas read FCanvas; protected function TransformPoint(X, Y: Double): TPoint; virtual; public constructor Create(ACanvas: TCanvas); procedure VisitShapeCircle(Instance: TShapeCircle); override; procedure VisitShapeRectangle(Instance: TShapeRectangle); override; end; implementation constructor TShapeVisitorCanvas.Create(ACanvas: TCanvas); begin inherited Create; FCanvas := ACanvas; end; function TShapeVisitorCanvas.TransformPoint(X, Y: Double): TPoint; begin Result := Point(Round(X), Round(Y)); end; procedure TShapeVisitorCanvas.VisitShapeCircle(Instance: TShapeCircle); var P1: TPoint; P2: TPoint; begin P1 := TransformPoint(Instance.CenterX - Instance.Radius, Instance.CenterY - Instance.Radius); P2 := TransformPoint(Instance.CenterX + Instance.Radius, Instance.CenterY + Instance.Radius); Canvas.Ellipse(P1.X, P1.Y, P2.X, P2.Y); end; procedure TShapeVisitorCanvas.VisitShapeRectangle(Instance: TShapeRectangle); var P1: TPoint; P2: TPoint; begin P1 := TransformPoint(Instance.X0, Instance.Y0); P2 := TransformPoint(Instance.X1, Instance.Y1); Canvas.Rectangle(P1.X, P1.Y, P2.X, P2.Y); end; end. |
It is worth to mention that the units Graphics and Types are only used in the new visitor unit. There is no reference to them in the unit describing the shapes.
The other visitors can be implemented in a similar way keeping all the specific stuff (Inifiles, OpenGL, XML) inside the visitor unit. This allows to only include the visitors we actually need and doesn’t pollute our uses clause with units we don’t want in our application.
More in Part 2…
Thanks for an excellent article on the visitor pattern. I have heard a lot of talk regarding patterns, but all very abstract in its descriptions. This one really makes it easy to understand.
Jan