空对象模式

Tig*_*ear 20 java oop null nullpointerexception null-object-pattern

似乎有越来越多的人说你永远不应该返回null,而应该总是使用Null对象模式.我可以在使用集合/ map /数组或调用boA函数(如isAuthenticated()时看到NOP的有用性,如下所示).

我没有发现任何完全令人信服的东西.当我试图组织我的想法时,请在这里忍受我.

我的理解是,不是返回一个空对象,而是返回一个已被"清零"的有效对象.

因此,例如,客户端将调用以获取对象:

Car car = getCar();
Run Code Online (Sandbox Code Playgroud)

如果不使用NOP,则需要在调用其上的任何方法之前检查从getCar()返回的对象是否为null:

if (car != null){
    color = car.getColor();
    doScreenStuff(color);
   }
Run Code Online (Sandbox Code Playgroud)

使用NOP,getCar()它现在返回一个已被有效"清零"的对象,而不是返回null.所以现在我们不再需要做if (car != null),只能请求颜色.因此,我认为当我们调用颜色时,我们的"归零"对象将返回"无".

这有什么用?似乎向前移动并在空对象上调用方法会导致与仅检查null相同的痛苦.现在,当需要显示信息时,我们需要检查颜色是否为"无",高度不为0,或者您拥有的其他任何值.因此,基本上,如果汽车为空,则不检查处理的开始,而是检查我们拥有的汽车对象是真车还是替代品.IE我们不想显示一堆空对象,所以我们需要一些方法来过滤掉所有空对象.

这个过滤是一个额外的步骤,就像调用if(car!= null)一样.唯一的区别是,通过检查null,我们可以在通过抛出异常发现car对象为null时立即停止处理,而使用NOP我们在空对象上调用方法并继续前进,直到它到达时间为止显示对象,此时我们过滤掉空心.此外,您需要知道空对象返回的值.IE确实getColor()返回"none"或"empty".

显然必须有一些我忽略的东西.提前致谢.

Lui*_*las 12

MattPutnam的回答是正确的,我是第二个.我要补充一点:当你分析它时,"空对象"的概念似乎归结为幺半群的数学概念.你可以这样想:monoid是一种具有这两种东西的类型:

  1. 需要关联的"附加","总和"或类似操作:a.op(b).op(c)与...相同a.op(b.op(c)).
  2. "空","零"或"空"值,用作操作的中性元素标识元素.

null对象模式的经典示例是返回空列表或数组而不是null.好吧,列表是一个monoid,作为操作追加,空列表作为中性元素.

现在,你在你的Car例子中面临的问题是,这Car不是一个真正的幺半群; 没有"空车"或"中性车"的概念,并且没有一个合理的操作可以用来将两个Cars 组合成一个.

所以你正确得到的建议是使用像Java 8这样的东西Optional.诀窍在于,无论是什么类型T,Optional<T>都是幺半群:

  1. monoid的"组合"操作是"如果不是empty,则选择第一个值,否则选择第二个值":
    • x || empty = x
    • empty || x = x
  2. 中性元素是Optional.empty()因为Optional.empty().orElse(anything)和刚才一样anything.

所以基本上,Optional<T>是一个包装器,它将null对象添加到Car没有一个类型的类型.该Optional<T>.orElse(T value)方法是"挑选第一个非empty值"幺半群的略微重构版本.


Mat*_*nam 8

只有null对象具有合理的功能值时,null对象模式才有意义.目的不是像你所描述的那样推迟null,而是通过用仍然有效的实际数据表示虚无或空虚来完全消除null的想法.例如,如Wikipedia文章中所述,树结构中的洞的自然情况.

空车没有意义.在这种情况下,getCar()回归似乎更合适Optional<Car>.