Max*_*kyi 5 java visitor visitor-pattern
我期待在访问者模式的解释在这里,显示下面的代码:
public class ShoppingCart {
public double calculatePostage() {
PostageVisitor visitor = new PostageVisitor();
for(Visitable item: items) {
item.accept(visitor);
}
public class PostageVisitor implements Visitor {
public void visit(Book book) {
public class Book implements Visitable{
public void accept(Visitor vistor) {
visitor.visit(this);
}
Run Code Online (Sandbox Code Playgroud)
从JavaScript开发人员的角度来看,该accept方法似乎是多余的,因为代码可以像这样编写:
for(Visitable item: items) {
// directly call visitor passing an item instead of doing so through `accept` method
visitor.visit(item);
}
Run Code Online (Sandbox Code Playgroud)
我是否正确地认为这不起作用,因为编译器不知道visit访问者的哪个重载方法要执行?
据我所知,编译器了解visit在visitorwith 上执行哪个方法,accept因为它可以匹配this传递给visitor.visit(this)方法的类型:
public void accept(Visitor vistor) {
visitor.visit(this);
}
Run Code Online (Sandbox Code Playgroud)
编辑:
刚刚发现除了这里的好答案之外,这个答案还提供了很多有用的细节.
我是否正确地假设这不会起作用,因为编译器不知道要执行访问者的哪个重载访问方法?
绝对地。访客为双重派遣;accept执行调度的第一段,因为它在item. 内部代码accept通过让编译器选择适当的重载来执行调度的第二段。
据我了解,编译器通过 accept 了解在访问者上执行哪个访问方法,因为它可以匹配传递给
visitor.visit(this)
这是完全正确的。我认为在访问者的这个实现中令人困惑的部分是超载。visit给每个重载一个单独的名称而不是重载时,更容易看到发生了什么。换句话说,而不是
public void visit(Book book);
public void visit(Cow cow);
public void visit(Island island);
Run Code Online (Sandbox Code Playgroud)
你写
public void visitBook(Book book);
public void visitCow(Cow cow);
public void visitIsland(Island island);
Run Code Online (Sandbox Code Playgroud)