The Visitor Pattern – Part 2

In Part 1 of this series we learned about the benefits of the Visitor Pattern and saw a basic approach according to the GoF description.

As clean and elegant the visitor pattern might look in the first place, it nonetheless has its disadvantages. Say, we want to add a new shape TShapeTriangle. We have to do it inside the same unit the other shapes are declared. As the shapes reference the visitor and the visitor references the shapes we have to put all shape classes together with the visitor into the same unit. Although this might work in some smaller scenarios, it definitely doesn’t in most of the real ones. Probably this is one of the reasons why the Visitor Pattern is not as famous as it should be.

Can we find a solution? Yes, we can!

Lets examine why there is such a close coupling between all the shapes and the visitor: The shapes use the visitor’s method corresponding to their own class and the visitor has to know about all the shapes it has to handle. How can we break this up?

The answer are interfaces! Instead of declaring a visitor capable of handling every defined shape, we declare an interface for each shape that only handles that specific shape.

Author: Uwe Raabe

Addicted to Pascal/Delphi since the late 70's

2 thoughts on “The Visitor Pattern – Part 2”

  1. I’d say the real reason the Visitor pattern doesn’t work in the real world is that the concrete examples where it makes sense (and the head spinning induced by trying to disentangle who actually ends up doing what and how) are simply too few and far between.

    This rendering example, for instance.

    The chances of needing to render to a canvas but not have to have any other interaction with the canvas are remote in the real world. e.g. in response to a mouse click determine which shape, if any, the user has clicked on.

    The information needed to make that determination is almost certainly involved in rendering the shape (the hit region will correspond to the rendered area). You could of course have a “HitTestVisitor”, which will have to duplicate a lot of the code already contained in the “RenderVisitor”, not to mention any number of other visitors.

    Also, any visitor can usually just work directly with the objects in question. No need to complicate things with invocation ping-pong with A visiting B just so that B can invoke A’s visit method. Just have A work directly against B and B doesn’t have to know anything about A at all.

    Or more succinctly: With the Visitor Pattern you can only visit things which actually accept visits. It’s by invitation only.

    It strikes me that you could implement a shape canvas renderer without even that level of coupling in a way that is much easier to understand and follow.

    Maybe this was just a sub-optimal example.

Comments are closed.