AspectJ 中的多态性
我正在尝试确定哪种是在 AspectJ 中分派类型的更好方法。 假设我正在对具有三种节点的树执行计算。然后我可以编写一个简单的 Java 方法:
private void computation(TreeNode node) {
if (node instanceof Node0) {
// Do stuff.
} else
if (node instanceof Node0) {
// Do stuff.
} else
if (node instanceof Node0) {
// Do stuff.
}
}
或者
private void computation(TreeNode node) {
switch (node.kindNode()) {
case NODE0:
// Do stuff.
break;
case NODE1:
// Do stuff.
break;
case NODE2:
// Do stuff.
break;
}
}
我可以将一个方法注入到每个节点类型中:
private void Node.computation() {
throw new UnsupportedOperationException(getClass() + ".computation()");
}
private void Node0.computation() {
// Do stuff.
}
private void Node1.computation() {
// Do stuff.
}
private void Node2.computation() {
// Do stuff.
}
哪种方法更可取,为什么?
I am trying to decide which is the better way to dispatch on a type in AspectJ.
Suppose I am performing a computation on a tree with three kinds of nodes. I could then write a simple Java method:
private void computation(TreeNode node) {
if (node instanceof Node0) {
// Do stuff.
} else
if (node instanceof Node0) {
// Do stuff.
} else
if (node instanceof Node0) {
// Do stuff.
}
}
or
private void computation(TreeNode node) {
switch (node.kindNode()) {
case NODE0:
// Do stuff.
break;
case NODE1:
// Do stuff.
break;
case NODE2:
// Do stuff.
break;
}
}
or I could inject a method into each node type:
private void Node.computation() {
throw new UnsupportedOperationException(getClass() + ".computation()");
}
private void Node0.computation() {
// Do stuff.
}
private void Node1.computation() {
// Do stuff.
}
private void Node2.computation() {
// Do stuff.
}
Which method is preferable and why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
什么是更好的很大程度上取决于具体情况。
如果我正确理解您的问题,您希望以某种方式事后将此“计算”方法添加到已经存在的类型层次结构中,并且更改原始类型的源代码不是一个选项,对吧?
在这种情况下,最重要的问题是:Node 类型层次结构的更改频率如何?因为任何这样的改变都可能会迫使你调整你的方面,这是一个维护问题。
话虽如此,您的第三个建议是“规范的”面向对象的解决方案。在一般编程中,它通常优于 switch-case 方法,因为后者往往会导致复杂且难以理解的代码,除非
computation()
中的操作非常简短。基本上,对于基于 AspectJ 的解决方案也是如此,就像您的情况一样。但是设置方面稍微困难一些,因为它必须在多个子类中注入定义,而在另一种情况下,当您选择 switch-case 解决方案时,您只需将一个小的转发方法注入到基类中然后从那里跳到一个保存你的开关类型的普通java类。访问者模式:实际上,您在这里所做的看起来就像访问者模式的经典用例,可以使用方面来优雅地实现。也许这将是最干净的解决方案,但访问者模式本身是一个高级主题(如果有兴趣,我可以更详细地解释)
what is preferrable very much depends on the situation.
If I understood your problem correct, you want somehow to add this "computation" method after-the-fact into an already existing type hierarchy, and changing the original types's source code isn't an option, right?
In this case, the most important question is: how frequent are changes to the Node type hierarchy? Because any such change will probably force you to adjust your aspect, which is a maintainance problem.
Having said that -- your third proposal is the "cannonical" object oriented solution. In general programming, it is usally preferred over the switch-case approach, because the latter tends to lead to complicated and difficult to understand code, unless the operations in
computation()
are very short and simple. Basically, the same holds true for an AspectJ based solution, as in your case. But it is slightly more difficult to set up the aspect, because it has to inject definitions in multiple subclasses, whereas in the other case, when you go for the switch-case solution, you would just inject a small forwarding method into the base class and jump from there into a plain java class holding your switch-on-type.visitor pattern: actually, what you do here looks like the classical use case for the visitor pattern, which can be implemented elegantly using an aspect. Probably that would be the cleanest solution, but the visitor pattern in itself is an advanced topic (I can explain in more detail if there is interest)