2

I was looking for the common usecases for the Visitor pattern. I could found some examples in the internet, but they are rather basic and only explain the concept, not when this pattern may really save your time/life.

Do you have a real world example using such pattern ? (i.e in an existing java project in Github for example)

I don't see clearly what problem does it solve in a large scale and why a developer may use it ?

devPsycho
  • 69
  • 1
  • 5
  • 1
    Possible duplicate of [When should I use the Visitor Design Pattern?](https://stackoverflow.com/questions/255214/when-should-i-use-the-visitor-design-pattern) – davidxxx Jul 27 '18 at 14:56

2 Answers2

3

Visitor pattern is useful when you want to send a message (i.e. invoke a method) to an object, but you cannot due to type-checking of compiler. For example, the object is declared to belong to type (interface) Animal which has only method say(), and you want to invoke method smile() on that object.

Yes, you could modify the interface Animal (to add the method smile()), but for some reason, you want to keep the interface stable. What if in the future you need more methods like go(), walk() ...?

Yes, you could cast the Animal object to every specific type you want e.g. Dog, Cat ... but for some reason, you want to keep this calling code stable in terms of not caring about specific animal types. What if in the future you have more animal types like Bird, Elephant ...? After all, the calling code just wants the object to smile and doesn’t want to be modified when there is a new specific type of the object.

So, let’s delegate all these unstable things to visitors. You will have SmileVisitor, GoVisitor, WalkVisitor ... with methods of visit(Dog), visit(Cat) ... and use them like this:

new SmileVisitor().visit(animal);

P/S: I think you can find some common usecases of keeping some part of source code stable by yourself.

Nghia Bui
  • 3,694
  • 14
  • 21
  • I like this answer as a student of design patterns but one dilemma remains. When you apply a method say `smile`, you have to know in advance (~presume?) that object is the one that supports this method? – zar Jul 30 '18 at 21:38
  • The calling code just want to make the animal smile. It does not need to know whether the exact name of method is “smile” or not. But the more important thing is: it does not need to know whether the animal is a dog or a cat. You know that object supports smile operation, but you don’t want to know its specific type (to make a down-cast and call smile). That’s the point. – Nghia Bui Jul 31 '18 at 00:52
2

Most people use the GoF book as a reference, but is not easy to read for those learning patterns (I know, I tried!).

Not meaning to interrupt or contradict Ravindra Ranwala, here is my English language description of Visitor and its purpose.

Lets say you have a "object structure" like a tree or whatever, whose elements are sub-classes of some base class - ie implement a common interface. There are a trillion examples of this, and its not unusual to traverse the structure, exercising the methods of the elements as you go.

A typical example of this is a parse-tree constructed by an arithmetic expression parser. When the tree is constructed you might invoke evaluate() on the head element and it would traverse the tree invoking evaluate() recursively through the tree to reach the result of the expression.

Now suppose you wanted to do something else with the tree, but unfortunately the elements do not have methods to support what you want to do. Enter Visitor, which involves adding a additional "programmable" method called accept() to every element.

We also need a separate Visitor object, one for each new "algorithm" we want to implement. Each Visitor object must implement a visit(NodeType n) method for each subclass of element. Meaning the new processing on each node, will depend of the type of the node visited.

Then you traverse the tree calling the accept(XVisitor vis) method in each element. The accept() method in turn invokes the vis->visit(this) passing a reference to itself back to the Visitor, which finally invokes the correct version of visit() for that node type.

So if your element objects are set up from the start to include the "programmable" accept() method, then you can do what the Visitor pattern promises - lets you "define a new operation without changing the classes of the elements on which it operates".

This is a simple idea actually, but confused by the mechanics to implement it and of course different languages go about it differently. So you have to plough through it for Java or PHP or whatever and details will differ.

The example in GoF is a abstract parse tree where you may later want to do some additional processing or type-checking or whatever, not envisaged when the tree was originally designed. Visitor allows a little "back-door" to do new things later, without disturbing either the element objects or the tree.

Hope this helps a bit...

bcperth
  • 2,191
  • 1
  • 10
  • 16
  • When do you set up the visitor pattern? The first time you create the interface and superclass, or do you setup the visitor pattern latter on when it becomes hard for you to add new functionality? – GilbertS Apr 08 '20 at 13:09