Design patterns 访问者设计模式中的方法命名
下面是visitor设计模式的上下文/示例代码Design patterns 访问者设计模式中的方法命名,design-patterns,Design Patterns,下面是visitor设计模式的上下文/示例代码 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 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();
}
}
我的指导老师说,重载visit
方法不是一个好主意,我应该为每个visit方法指定一个不同的名称,如下所示。我不相信这个想法。有人能解释一下重载visit
方法的缺点吗
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();
}
}
《四人帮》一书,又名《圣经》,是按照你的导师的建议来做的 Visitor类在C++中的声明如下:
class Visitor {
public:
virtual void VisitElementA(ElementA*);
virtual void VisitElementB(ElementB*);
// and so on for other concrete elements
protected:
Visitor();
};
案件结案
请看我在@vadya上面的回答:重载意味着方法做相同的事情,但在不同类型上支持相同的事情,而Visitor则不是这样 根据我的理解,访问者设计模式的目的是解决单一调度问题。
访客模式提供了双重分派方法。动态分派仅基于调用对象的类型,该类型只能使用重写而不是重载。 使用重载将使函数依赖于调用期间传递的参数,我们不希望在visitor中使用该参数 使用重载覆盖的整体概念是在访问者中实现双重调度机制 John Vlissides的书《模式孵化》(GOF作者之一,他的书有时被认为是设计模式的补充)解释了实现Visitor的两种方法的优点 他说使用不同变量名的原因是: 当存在resonalbe默认行为时,一个更重要的优势就出现了,并且子类往往只覆盖一些操作。当我们重载时,子类必须覆盖所有函数;否则,友好的C++编译器可能会抱怨,你的选择性重写隐藏了一个或多个基类操作。当我们给访客操作起不同的名字时,我们绕过了这个问题。然后子类可以重新定义操作的子集而不受惩罚。 -图案填充第36页
我也想知道这个问题的答案,因为我同意你的看法。我从未见过这样的实现。除了笨拙地阅读之外,我发现有反映您访问的抽象的方法名称是很奇怪的。参数已经涵盖了这一点。@Vidya然后放弃投票:DDone。让我们看看会发生什么。这背后的原因是什么?我可以在教科书中找到使用过载的例子,但这并不能回答我的问题。我想说,如果你认为“四人帮”是错误的,你需要提供理由。我通常尽量避免在类型为param的方法中提及类型,但我认为在这种情况下这是有意义的,因为访问者的整个想法是所有做任何事情的方法都在一个地方。我和下一个家伙一样喜欢Go4和设计模式的想法,但是,盲目地、虔诚地毫无疑问地接受某些东西,这在任何事情上都是一个坏主意。除此之外,OP并没有说Go4是“错误的”。他是在问为什么他的想法也行不通。这比黑白对错问题更加微妙。让我们不要忘记来自欧比万的伟大。是的,《星球大战》不是我选择的道德文本,但谢谢你。我认为你错了,op是说他认为他的教练和Go4是错的。除了op实际上从来没有用“错”这个词。他说他“不相信这个想法”。我不相信无脂牧场敷料的想法,但我也不会称之为“错”。您似乎推断的比您应该推断的要多。“动态分派仅基于调用对象的类型,该类型只能使用重写而不是重载”<不正确根据我的理解,动态调度机制是我们所说的运行时多态性,它在运行时得到解决,而重载是编译时绑定,如果您能给我提供一些示例来证明该语句是错误的,这将对我和改进该概念有很大帮助。谢谢,这听起来是个很好的论点。这是一个C++ C++特有的代码>特性/代码>,还是在OO语言(C,java)中的一般行为?我认为这是C++特定的行为。对于java,根据JLS§9.4.1.:在逐个签名的基础上重写方法<代码>例如,如果一个接口声明了两个同名的公共方法(§9.4.2),并且子接口重写了其中一个,则子接口仍然继承另一个方法代码>