空虚或虚拟物体?

时间:2012-11-19 02:59:08

标签: java oop design-patterns

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

  

注意:监听器注册完全是可选的,用户可能想要   在没有注册任何听众的情况下打电话给工作。

问:您喜欢以下哪种解决方案?为什么?

  

编辑:此处的关注点是效果干净代码。有人说,与第二个解决方案相比,检查空引用(解决方案1)更快。但第二种解决方案更清洁,更易理解。我想听听您的意见。

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

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

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

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 个答案:

答案 0 :(得分:4)

你认为if x==null是一种代码气味是正确的,它肯定是!

使用Null Object模式的原因非常正确,一个是避免使用if (x == null)噪音乱丢您的代码,这些噪音通常与业务相关性较差,设计相关性较差。 NULL表示缺少值默认值。

我认为你没有采用Null Object模式。

永远不会返回null,你永远不必检查它

首先从方法中取消return null,然后在代码中永远不要if x == null。两者都是设计不佳的明显迹象。 null引用和NPE应该是一个错误,应该在没有发生的情况下解决。

永远不要接受null,你永远不必检查它。

拥有return null返回Null Object并且接受null并且可能会处理null引用的方法具有Null Object实现来处理Null References的方法。< / p>

在您的情况下,您的Dummy对象不会不执行任何操作,它应该向日志警告报告它遇到了{{1}关于它应该做些什么。

使用一个好的JSR305库来注释你的方法,这样他们就不会'接受空值。

我在我创建的每个Java程序中都有com.google.code.findbugs maven依赖项,无论多么微不足道,我都可以使用null修饰每个方法和方法参数,而不必担心编写{{1再一次!

如果你有第三方代码返回@NONNULL包装并使用JSR305注释。

将Guava if x == nullnull导入一起使用,以便对标记为Preconditions.checkNotNull()的所有参数static进行操作,甚至可以包含有关内容的描述性错误消息是checkNotNull(),为什么它不应该是什么。

沾沾自喜地想一想他们的代码设计得不好。

答案 1 :(得分:1)

我会将批处理作业建模为Observable,将监听器建模为Observer。可以在用于通过notifyObservers(object)方法与Observers通信的对象中跟踪批处理作业中的状态更改。

答案 2 :(得分:-1)

答案取决于default listener背后的真实意图。如果你的默认监听器(Dummy)没有做任何事情,那么就不需要创建这样的监听器。带有Null的{​​{1}}仅用于处理此类方案(更高效,更紧凑)。

但另一方面,如果你想通过默认监听器实现一些默认行为,那么你应该创建默认监听器。

作为一个拇指规则,在有任何使用/要求之前,我不会将程序与对象混在一起。

答案 3 :(得分:-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想法不会增加任何价值。使用null变得清晰明了 - 如果监听器是null(即什么都没有),每个人都知道发生了什么,并且在调试时更明显。