A few weeks ago, I described here the Open-Closed Principle, which says that software entities should be open for extension, but closed for modification. Now, imagine you are facing with the following design problem:
You need to add a new functionality to a hierarchy of classes, but the act of adding it will be painful or damaging to your design.
I’ll use here the example of Robert C. Martin’s book: suppose you have a hierarchy of Modem objects. The base class has the generic methods common to all modems, and the derivatives represent the drivers for many different modem manufactures and types. Suppose also that you have a requirement to add a new method, named configureForUnix, to the hierarchy. This method will configure the modem to work with the UNIX operating system, corresponding to a different implementation in each modem derivative.
The real problem is not adding the new configureForUnix method, but what about the others operating systems? Must we really add a new method to the Modem hierarchy for every new operating system? Adding methods to the hierarchy of classes obviously violates the OCP because we’ll never be able to close the Modem interface.
The VISITOR pattern helps solving this kind of problems. As it definition says: VISITOR lets you define a new operation without changing the classes of the elements on which it operates. To do that, VISITOR use a technique called dual dispatch, which evolves two polymorphic dispatches.
The figure below shows the UML diagram create by VS2008.
Now, let’s create the code necessary to implement the VISITOR pattern in the Modem problem.
And here is the test code.
Having built this structure, new operation system configuration can be added just by creating new derivatives of ModemVisitor without changing the Modem hierarchy. Another pattern that accomplishes this is the DECORATOR pattern, but this is a talk for other post.