The visitor allows adding common behavior to unrelated types. It should be used if we cannot or don’t want to change the source code of the given types.
- It separates the new behavior into a dedicated visitor. The visitor must visit each object and performs required operations on that object’s state.
- If a new functionality is required, you must only extend the visitor, or create a new visitor for that matter.
- This pattern is useful if you need to traverse collections of heterogeneous objects and perform related operations.
- The visitor works without subclassing.
The visitor lets us add new common behavior to unrelated types without changing their implementation.
Example: Suppose we have added a set of unrelated products, Book, Computer, and Car into a shopping cart of an online store. They have different properties for retrieving their price; itemPrice for Book, unitPrice for Computer, and stickerPrice for Car. So at the time of price calculations we need to check the product type and accordingly call its prie property. This is problematic when the product type list grows.
The visitor patterns solves this problem by extracting the new behavior into a visitor type. The visitor has visit methods that can handle each and every type. So, I declare the Visitor protocol with a visit method for each of the type Book, Computer, and Car. This interface for each type is defined in concrete class of visitor class.
Each product accepts a visitor and then the product calls the visit method of the visitor. This method knows how to calculate price of the product of particular type. Accepting a visitor and calling its visit method – this is called double dispatch.
Double dispatch :
The concrete visitor types need to operate on the subject state. To receive the right instance, the visitor pattern uses a technique called double dispatch. For double dispatch to work, each type has to define an accept visitor method.
The accept method takes a visitor instance as an input argument. Calling the accept method ensures that the current subject gets chosen. For each subject, I implement the accept visitor method.
Accept visitor calls the visitor’s visit method with self as argument. This calls the correct visitor subclass and ensures that the right operation gets executed. The process is called double dispatch because of calling the accept and the visit methods.
In simple words : The visitor should be used to add new behavior to unrelated types without the need of subclassing. No such pitfalls however the concrete visitor interface can grow if abstraction is not done right.