4

考虑一个可能需要也可能不需要很长时间才能完成工作的批处理操作(取决于数据)。用户可以注册一个可选的监听器来跟踪作业进度。

注意:监听器注册是完全可选的,用户可能希望在不注册任何监听器的情况下调用作业。

问:以下哪种解决方案是您的首选,为什么?

编辑:这里关心的是性能干净的代码。有人说,与第二种解决方案相比,检查空引用(解决方案 1)更快。但第二种解决方案更干净,更容易理解。我想听听你的意见。

否 1:允许空侦听器并始终检查侦听器是否不为空,然后调用它。

doMyBatchJob() {
   if (listener != null) {
      listenr.progressStarted(params);
   }
   while (x) {
      if (listener != null) {
          listener.progressUpdated(current, expected)
      }
   }
   if (listener != null) {
      listenr.progressFinished(params);
   }
}

No 2:实现一个虚拟监听器,如果用户没有通过他/她自己的监听器,则注册它。这样就可以在不检查空对象的情况下调用侦听器。

DummyListener {
     public void progressStarted(params) { //DO NOTHING }
     public void progressUpdated(current, expected) { //DO NOTHING }
     public void progressFinished(params) { //DO NOTHING }
}

doMyBatchJob() {
   listener.progressStarted(params);
   while (x) {
         //Do a single unit of the batch operation
         // ... code omitted here
         listener.progressUpdated(current, expected)
   }
   listener.progressFinished(params)
}
4

4 回答 4

4

您对if x==null代码异味的担忧是正确的,这绝对是!

使用该模式有非常正当的理由Null Object,一个是避免在您的代码中乱扔if (x == null)噪音,这些噪音通常与业务相关性较低,与设计相关性更差。NULL表示没有值而不是默认值。

我认为您对Null Object模式的了解还不够。

永远不要返回 null 并且您永远不必检查它

首先,永远不要return null来自方法,也永远不要if x == null在你的代码中。两者都是设计不佳的肯定迹象。null引用并且NPE应该是一个错误,应该在没有发生的地方解决。

永远不要接受 null 并且您永远不必检查它。

具有return null返回 a 的方法,Null Object并具有接受 null 并且可能处理null引用的事物具有Null Object处理Null References.

在您的情况下,您的Dummy对象不仅不会做任何事情,它还应该向日志警告报告它遇到了 anull并且应该对其进行处理。

使用一个好的 JSR305 库来注释您的方法,以便它们不接受空值。

com.google.code.findbugs在我创建的每个 Java 程序中都有 maven 依赖项,无论多么微不足道,我都可以用它来装饰每个方法和方法参数,@NONNULL而不必担心if x == null再次编写!

如果您有返回null包装它的第 3 方代码并使用 JSR305 注释。

将 GuavaPreconditions.checkNotNull()static导入一起使用,这样您就可以checkNotNull()对所有标记的参数执行操作@Nonnnull,您甚至可以包含关于什么是的描述性错误消息,null以及为什么它不应该是或其他什么。

并且得意地想想他们的代码设计得多么糟糕。

于 2012-11-19T13:37:40.437 回答
1

我会将批处理作业建模为 anObservable并将侦听器建模为Observer. notifyObservers(object)批处理作业中的状态更改可以在用于通过该方法与观察者通信的对象中进行跟踪。

于 2012-11-19T03:11:07.593 回答
-1

答案取决于背后的真实意图default listener。如果您的默认侦听器(虚拟)不做任何事情,则无需创建此类侦听器。Nullwithnull-check仅用于处理此类场景(更高效和紧凑)。

但另一方面,如果您希望通过默认侦听器实现一些默认行为,那么您应该创建默认侦听器。

作为一个经验法则,在有任何使用/需求之前,我不会用对象来挤满程序。

于 2012-11-19T03:10:38.257 回答
-1

我都不会。我会使用选项 1,但大大简化了:

doMyBatchJob() {
   if (listener == null) {
       return; // if listener is null, do nothing
   }
   listener.progressStarted(params);
   while (x) {
      listener.progressUpdated(current, expected)
   }
   listener.progressFinished(params);
}

这遵循“早日退出”的口头禅。此外,它不会导致“类膨胀”——你的DummyListener想法没有任何价值。使用 anull代替是干净和清晰的 - 如果侦听器是(即什么都没有),每个人都知道发生了null什么,并且在调试时更加明显。

于 2012-11-19T04:03:35.217 回答