在动态语言中实现访问者模式的首选方法?
作为我自己的练习,我正在将示例程序翻译成各种语言。 从 C# 开始,我有一个访问者模式界面,如下所示:
interface Visitor
{
void Accept(Bedroom x);
void Accept(Bathroom x);
void Accept(Kitchen x);
void Accept(LivingRoom x);
}
转向 ruby(或 python,或其他),我不再根据类型从编译器获取调度。 我应该在访客本身进行调度吗?
class Cleaner
def accept(x)
acceptBedroom(x) if Bedroom === x
acceptBathroom(x) if Bathroom === x
acceptKitchen(x) if Kitchen===x
acceptLivingRoom(x) if LivingRoom===x
end
...
或者我应该在房间的不同专业中进行调度:
class Bathroom<Room
def initialize(name)
super(name)
end
def accept(visitor)
visitor.acceptBathroom(self)
end
end
或者动态语言中是否有另一种首选的习惯用法?
As an exercise for myself, I was translating a sample program into various languages. Starting in C#, I had a visitor-pattern interface like so:
interface Visitor
{
void Accept(Bedroom x);
void Accept(Bathroom x);
void Accept(Kitchen x);
void Accept(LivingRoom x);
}
Moving to ruby (or python, or whatever), I no longer get dispatch from the compiler based on type. Should I do the dispatch in the visitor itself?
class Cleaner
def accept(x)
acceptBedroom(x) if Bedroom === x
acceptBathroom(x) if Bathroom === x
acceptKitchen(x) if Kitchen===x
acceptLivingRoom(x) if LivingRoom===x
end
...
Or should I do the dispatch in the different specializaions of the room:
class Bathroom<Room
def initialize(name)
super(name)
end
def accept(visitor)
visitor.acceptBathroom(self)
end
end
Or is there another preferred idiom that is used in dynamic languages?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我会选择第二个版本。 第一个看起来像是 Visitor 应该解决的代码味道:长 if-else-if 或 switch-case 语句。
I would go with the second version. The first one looks like the kind of code smell that Visitor is supposed to solve: long if-else-if or switch-case statements.
我的建议是使用前一种方法。 每种方法都有优点和缺点。 随着 Room 类型数量的增加,前者更难维护; 随着清洁工类型数量的增加,后者变得更加困难。
在 Ruby 中,你可以尝试
PS:并非所有动态类型语言都无法基于类型进行调度; 有些可以推断类型,或者无法推断类型,可以使用强制转换在重载选项中选择正确的方法。
My recommendation is to use the former approach. There are pluses and minuses for each approach. The former is harder to maintain as the number of Room types grows; the latter is harder as the number of Cleaner types grows.
In Ruby, you could try
PS: not all dynamically typed languages are unable to do dispatch based on type; some can infer type, or failing that, can used forced casting to pick the proper method among the overloaded options.