Hello, thought I'd ask before getting too deep into code to make sure I understand this properly.
As described in the Gamma et. al. book the Visitor Pattern looks something like this:
interface Visitor{
public void visitX(X x);
public void visitY(Y y);
public void visitZ(Z z);
}
interface Visited {
public void visit(Visitor v);
}
class X implements Visited{
public void visit(Visitor v){
v.visitX(this);
}
}
class Y implements Visited{
public void visit(Visitor v){
v.visitY(this);
}
}
class Z implements Visited{
public void visit(Visitor v){
v.visitZ(this);
}
}
//SOMEWHERE ELSE A CLASS
public void doAlgorithm(Visitor visitor){
for(Visited v : datastructure){
v.visit(visitor);
}
}
The book mentions doing the same with overloading so that would become:
interface Visitor {
public void visit(X x)
public void visit(Y y)
public void visit(Z z)
}
interface Visited {
public void visit(Visitor v);
}
class X implements Visited{
public void visit(Visitor v){
v.visit(this);
}
}
class Y implements Visited{
public void visit(Visitor v){
v.visit(this);
}
}
class Z implements Visited{
public void visit(Visitor v){
v.visit(this);
}
}
//SOMEWHERE ELSE IN A CLASS
public void algorithm(Visitor visitor){
for(Visited v : datastructure){
v.visit(visitor);
}
}
I may be very off on this but this leads me to think that this would work as well:
interface Visitor{
public void visit(X x);
public void visit(Y y);
public void visit(Z z);
public void visit(Visited v);//as a default
}
abstract class Visited{
public final void visit(Visitor v){
v.visit(this);
}
}
class X extends Visited {}
class Y extends Visited {}
class Z extends Visited {}
//SOMEWHERE IN A CLASS
public void algorithm(Visitor visitor){
for(Visited v : datastructure){
v.visit(visitor);
}
}
But as I understand it the method used is decided at compile time, so this would always call visit(Visitor)
, the reason I include this method in the first place is, I want to make the application extensible with the possibility of extending the amount of classes that exted Visited
with a user defined class I don't want to break the existing visitors. Would the proper implementation of Visited.visit(Visitor)
be:
public void visit(Visitor v){
try{
Method m = v.getClass().getMethod("visit", getClass());
m.invoke(v,this);
} catch(Exception e){
v.visit(this);
}
}
Which would actually render the Visitor interface moot, as it inspects the class itself. Can someone clarify this please?