【发布时间】:2009-03-24 21:30:32
【问题描述】:
在当前的 Java 项目中,我们有类似于以下示例的代码:
try {
doSomeThing(anObject);
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
try {
doOtherThing(anObject);
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
// ... some more calls to different method ...
try {
finallyDoYetSomethingCompletelyDifferent(anObject);
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
如您所见,使用完全相同的对象调用了几个不同的方法,并且对于每次调用,都会捕获和处理相同的异常(或以非常相似的方式)。异常不会重新抛出,而只能被记录然后丢弃。
每个方法周围都有一个try-catch 的唯一原因是始终执行所有方法,无论之前执行的方法是否失败。
我根本不喜欢上面的代码。它占用大量空间,非常重复(尤其是在catch-block 中完成的日志记录;此处未介绍)而且看起来很糟糕。
我可以想到一些其他的方法来编写这段代码,但也不是很喜欢它们。我想到了以下选项:
循环切换序列/for-case 范例
for (int i = 0; i <= 9; i++) {
try {
switch (i) {
case 0:
doSomeThing(anObject); break;
case 1:
doOtherSomeThing(anObject); break;
// ...More cases...
case 9:
doYetSomethingCompletelyDifferent(anObject); break;
}
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
}
这显然是糟糕的代码,非常容易出错并且看起来很业余。
反思
使用反射来获取Method 对象,以便方法调用并将它们按应该执行的顺序存储在列表中。然后遍历此列表并使用anObject 作为唯一参数调用该方法。异常在循环内部处理。
我不喜欢这种方法,因为错误(例如方法名称中的拼写错误)只会在运行时弹出,而且反射 API 有点啰嗦。
函子
像这样创建一个 Functor 类:
private class Functor
{
void doStuff(MyObject object) throws SameException;
}
然后创建调用方法的Functor 对象列表。像这样:
List<Functor> functors = new ArrayList<Functor>();
functors.add(new Functor() {
@Override
public void execute(MyObject anObject) {
doSomeThing(anObject);
}
});
functors.add(new Functor() {
@Override
public void execute(MyObject anObject) {
doOtherSomeThing(anObject);
}
});
稍后,迭代此列表并在每个 Functor 对象上调用 execute()。
我可以用两个词来概括我对这种方法的感受:代码膨胀。
由于我不太喜欢所有四种方法,因此我想在这里讨论这个问题。你觉得最好的方法是什么?您过去是如何解决类似问题的?有没有我完全错过的更简单的解决方案?
【问题讨论】: