I am working on a GUI application which generates a configuration file. I have a class hierarchy for the configuration model and I use an object tree of that hierarchy in several different contexts. Currently, I use the Visitor pattern to avoid polluting my model classes with context specific code.
interface IConfigurationElement {
void acceptVisitor(IConfigurationElementVisitor visitor);
}
In an earlier version I used chains of instanceof
conditions instead of the Visitor. Comparing the two approaches I see the following tradeofs.
Visitor
- It is easier and safer to add new
IConfigurationElement
. Just add a new declaration toIConfigurationElementVisitor
and the compiler generates errors for all visitor implementations. Withinstanceof
chains you have to remember all the places you have to extend with the new configuration element. Basicallyinstanceof
violates the DRY principle as it duplicates logic in several places. - The visitor pattern is more efficient than a chain of
instanceof
conditions
instanceof
- The great advantage of
instanceof
is its flexibility. For exampleinstanceof
allows me to define special solutions for different subsets ofIConfigurationElement
implementations which need to be handled similarilly in some cases. In contrast, Visitor forces me to implement a method for each implementation class every time.
Is there a common solution for this kind of problem? Can I adapt the Visitor somehow, so I can provide a common solution for some cases?
Best Answer
You could use visitor with instanceOf
interfaces:
Visitables:
Visitors:
each class knows only about its related interfaces, so adding new vistors nor visitables requires changing everything in that category (visitor/visitable) (for visitor, it does not require changing anything, for visitable it requires creating new visitor interface, but again, no changing of existing objects).
This way, there is no chain of instanceof tests and visitor for subset does not need to even know about types outside this subset.
Question is what to do with situation where A extends B (and B is Visitable too), in that case, you could just add super.accept(visitor) into accept (thus it would be short chain of instanceof-s, but onlu as long as hierarchy is deep, and it should not be too deep to matter, abd you don't need to write it whole manually).