Reputation: 7040
Here's the context/sample code of the Visitor design pattern:
public interface Visitable{
public void accept(Visitor v);
}
public class Book implements Visitable{
public void accept(Visitor v){
v.visit(this);
}
public void read() {}
/**
book stuff
**/
}
public class Movie implements Visitable{
public void accept(Visitor v){
v.visit(this);
}
public void watch() {}
/**
movie stuff
**/
}
public interface Visitor{
public void visit(Book b);
public void visit(Movie m);
}
public class Person implements Visitor{
public void visit(Book b){
b.read();
}
public void visit(Movie m){
m.watch();
}
}
My instructor says that it's not a good idea to overload the visit
method and I should give a distinct name to each visit method that looks like the following. I'm not convinced by this idea. Can someone explain what's the downside of overloading the visit
method?
public interface Visitor{
public void visitBook(Book b);
public void visitMovie(Movie m);
}
public class Person implements Visitor{
public void visitBook(Book b){
b.read();
}
public void visitMovie(Movie m){
m.watch();
}
}
Upvotes: 9
Views: 1717
Reputation: 2891
Honestly, it's just old people speaking. With an IDE, these days, going out of your way to name something:
class Visitor {
public void VisitElementA(ElementA a);
public void VisitElementB(ElementB b);
}
Is just redundant and a waste of precious horizontal space. You can easily and remorselessly just press whatever key combo tells your ide to give you a popup with all the posibile input types.
It's doubly pointless when virtually all implementations of visiotrs end up looking like this anyway:
class VisitableExample implements Visitable {
public void accept(Visitor v) {
v.visit(this);
}
}
Upvotes: 0
Reputation: 31658
John Vlissides's book Pattern Hatching (one of the GOF authors and his book is sometimes considered a supplement to Design Patterns) explains the advantages both both ways to implement Visitor.
The reason he says using the different variable names is this:
A more substantial advantage comes when there's a resonalbe default behavior, and subclasses tend to override just a few of the operations. When we overload, subclasses must override all of the functions; otherwise your friendly C++ compiler will probably complain that your selective overrides hide one or more of the base class operations. We get around this probelm when we give Visitor operations difference names. Subclasses can then redefine a subset of the operations with impunity. - Pattern Hatching p.36
Upvotes: 7
Reputation: 11733
The Gang of Four book, aka the Patterns Bible, does as your instructor advises.
The Visitor class would be declared like this in C++:
class Visitor { public: virtual void VisitElementA(ElementA*); virtual void VisitElementB(ElementB*); // and so on for other concrete elements protected: Visitor(); };
Case closed.
See my point on @vadya's answer above: overloading implies that the methods do the same thing, but support that thing on different types, which is not the case with Visitor.
Upvotes: -1
Reputation: 433
As per my understanding the purpose of the Visitor Design pattern was to solve the problem of single Dispatch problem. Visitor Pattern provides Double Dispatch approach. Dynamic dispatch is only based on the type of the calling object that is only possible using overriding not Overloading. Using Overloading will let the function depends upon the argument passed during calling which we don't want in visitor.
The whole concept of using overriding over overloading is to achieve Double Dispatch mechanism in visitor.
Upvotes: 0