The Visitor pattern allows operations on objects to be written without extending the object class. Sure. But why not just write a global function, or a static class, that manipulates my object collection from the outside? Basically, in a language like java, an accept()
method is needed for technical reasons; but in a language where I can implement the same design without an accept()
method, does the Visitor pattern become trivial?
Explanation: In the Visitor pattern, visitable classes (entities) have a method .accept()
whose job is to call the visitor's .visit()
method on themselves. I can see the logic of the java examples: The visitor defines a different .visit(n)
method for each visitable type n
it supports, and the .accept()
trick must be used to choose among them at runtime. But languages like python or php have dynamic typing and no method overloading. If I am a visitor I can call an entity method (e.g., .serialize()
) without knowing the entity's type or even the full signature of the method. (That's the "double dispatch" issue, right?)
I know an accept method could pass protected data to the visitor, but what's the point? If the data is exposed to the visitor classes, it is effectively part of the class interface since its details matter outside the class. Exposing private data never struck me as the point of the visitor pattern, anyway.
So it seems that in python, ruby or php I can implement a visitor-like class without an accept method in the visited object (and without reflection), right? If I can work with a family of heterogeneous objects and call their public methods without any cooperation from the "visited" class, does this still deserve to be called the "Visitor pattern"? Is there something to the essence of the pattern that I am missing, or does it just boil down to "write a new class that manipulates your objects from the outside to carry out an operation"?
PS. I've looked at plenty of discussion on SO and elsewhere, but could not find anything that addresses this question. Pointers welcome.