Often from a novice developer perspective the visitor design pattern looks like a mysterious pattern. But indeed it is a more powerful and beautiful design pattern if you understand it correctly (same applies to the woman you love 🙂 ). To understand this pattern correctly you must first have a clear idea of what problem visitor pattern tries to solve. In this two part blog post series I tried to explain why and when to use visitor design pattern from a different perspective.
What problem visitor design pattern solves?
When you google visitor pattern, You most likely find yourself on the related Wikipedia article, showing the following definition.
“In object-oriented programming and software engineering, the visitor design pattern is a way of separating an algorithm from an object structure on which it operates.”
Let’s try to look at the above said definition in detail, it states that using visitor pattern we can separate algorithm from an object structure. we all know algorithm is nothing but a set of instructions that solves a problem. And in object oriented programming usually instructions are encapsulated within the methods of an object. So is that mean visitor pattern tries to separate methods from an object? before answering this question let’s have a quick look on what it means “separating a method from an object” ? for example consider the following class Now if you want to separate the getContentAsHTML method from Document class to other class you can do something like as follows Now the important question is if we could able to separate a method from a class as simple as shown above then what is the need of visitor pattern? Again read the visitor pattern definition carefully it says “visitor tries to separate algorithm from an object structure” notice the word object structure. What you saw in the preceding code example is how to separate a method from a single object/class. So the next question is what is object structure? and how to separate algorithm from an object structure?
An object structure is nothing but a collection of objects associated with each other in a certain order.
Take an example of java.util.List it is an object structure where each object in the list are linearly associated. Similarly think about “Tree” data structure it is also an object structure where each object in the tree are hierarchically associated. So now we got a clear idea about what is an object structure. Before jumping into “how to separate an algorithm from an object structure?” let’s try to find answer for an important question “why should we need to separate an algorithm from an object structure?”
Why to separate algorithm from an object structure?
Well if we separate an algorithm from an object structure we get the flexibility of executing different algorithm on the object structure based on our requirement. we can switch different algorithm based on the context and apply it on the same object structure to get the desired result. Confused? let’s see an example to get clarify. consider the following classes DocumentPart is an abstract class which represents a part of a Document. A DocumentPart can be of PlainText, BoldText or HyperLink as follows and finally we have a Document class which as an object structure to represent a document consists of collection of DocumentPart Now imagine if we want an algorithm to convert this Document into HTML format, we can have an abstract method called toHtml in the DocumentPart class. So that every descendant derived class overrides that method and all the concrete DocumentPart class overrides toHtml method as follows And the aggregate Document class looks like as follows Now by calling Document.toHtml() method we can get the equivalent html content of Document object. But what if we want support for two more document conversion algorithm. For example imagine our Document object need to be converted into formats like plain text and wiki markup then we may need to introduce two more abstract method in the DocumentPart class as follows; and all the derived class of DocumentPart will get extra two methods in it as follows Now the aggregate Document class would become as follows
The real problem
This approach having two serious problem
- Consider If we want to add support for LaTeX markup conversion algorithm, then we need to introduce toLatex method in every concrete class of DocumentPart class. So each time we add an algorithm to an object structure we need to add methods in every single class of that object structure to support it.
- Second it violates The Open/closed principle of object oriented design. For example consider if we want to perform some operation based on the type of the DocumentPart object, we may end up in a growing list if else structure based on the number of derived type of DocumentPart class. Are you confused? to understand what I really mean, look at the following code snippet
Now if we introduce one more class called ItalicsText under the hierarchy of DocumentPart we need to change the above shown process method to accommodate one more if else condition for processing ItalicsText object. So to rectify the first problem we need to separate the algorithms from the object structure, So that we can add as many as algorithm to the object structure without disturbing the objects (elements) of the underlying object structure. So now you got the answer for why we need to separate an algorithm from the object structure. And to address the second problem of open/closed principle violation we need to use an object oriented technique called double dispatch. Visitor design pattern helps to separate algorithm from an object structure and also uses double dispatch technique effectively.
I hope now you clearly understood, what problem visitor design pattern tries to solve. In my next post I will explain how to use visitor design pattern effectively to separate an algorithm from an object structure, what is double dispatch and how visitor pattern employs double dispatch. we will also see what are all the advantage and disadvantage of this pattern. So stay tuned!!!.