似乎有越来越多的人说您永远不应该返回 null,而应该始终使用 Null 对象模式。在使用集合/映射/数组或调用诸如 isAuthenticated()、which is shown here 等 boolean 函数时,我可以看到 NOP 的用处。 .
我在这方面没有找到任何令人信服的东西。在我尝试整理我的想法时,请耐心等待。
我的理解是,您不是返回一个空对象,而是返回一个已“归零”的有效对象。
例如,客户端会调用来获取一个对象:
Car car = getCar();
如果不使用 NOP,您需要在调用任何方法之前检查从 getCar() 返回的对象是否为 null:
if (car != null){
color = car.getColor();
doScreenStuff(color);
}
使用 NOP,而不是 getCar()
返回 null,它现在返回一个已有效“归零”的 Object。所以现在我们不再需要执行 if (car != null)
并且可以只请求颜色。所以,我想当我们调用颜色时,我们的“归零”对象会返回“无”。
这有什么帮助?似乎向前移动并在空对象上调用方法会导致与检查 null 一样多的痛苦。现在,当需要显示信息时,我们需要检查颜色是否为“无”,高度是否为 0,或者您拥有的任何其他值。所以本质上,不是在处理开始时检查汽车是否为空,而是在之后检查我们拥有的汽车对象是真车还是替代品。 IE。我们不想显示一堆空对象,所以我们需要一些方法来过滤掉我们所有的空对象。
这个过滤是一个额外的步骤,就像调用 if (car != null) 一样。唯一的区别是,通过检查 null,我们可以通过抛出异常来在发现汽车对象为 null 时立即停止处理,而使用 NOP,我们调用空对象上的方法并继续运行,直到时间到了显示对象,此时我们过滤掉空对象。此外,您需要知道空对象返回的值。 IE。 getColor() 是否返回“none”或“empty”。
显然我忽略了某些东西。 提前致谢。
最佳答案
MattPutnam 的回答是正确的,我支持它。我要补充一点:“空对象”的概念,当您分析它时,似乎可以归结为 monoid 的数学概念。 .你可以这样想:一个幺半群是一种同时具有这两个东西的类型:
- 需要关联的“追加”、“求和”或类似操作:
a.op(b).op(c)
与a.op(b.op(c))
相同. - 一个“空”、“零”或“null”值,充当操作的中性元素或身份元素。
空对象模式的经典示例是返回一个空列表或数组而不是 null。嗯,列表是一个幺半群,追加作为操作,空列表作为中性元素。
现在,您在 Car
中遇到的问题例如 Car
不是真正的幺半群;没有“空车”或“空车”的概念,也没有真正明智的操作可以用来组合两个 Car
合而为一。
因此,您得到的正确建议是使用 Java 8 Optional
之类的东西。 .诀窍是无论是什么类型T
是,Optional<T>
是一个幺半群:
- monoid 的“组合”操作是“如果不是
empty
,则选择第一个值,否则选择第二个值”:-
x || empty = x
-
empty || x = x
-
- 中性元素是
Optional.empty()
, 因为Optional.empty().orElse(anything)
与anything
相同.
所以基本上,Optional<T>
是一个将空对象添加到像 Car
这样的类型的包装器。没有一个。 Optional<T>.orElse(T value)
方法是“选择第一个非 empty
值”幺半群的略微重构版本。
关于java - 空对象模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30717957/