Null 检查空对象模式
空对象模式的主要目标是确保向客户端提供可用的对象。 替换下面的代码...
void Class::SetPrivateMemberA() {
m_A = GetObject();
}
void Class::UseA() {
if (m_A != null) {
m_A.Method();
} else {
// assert or log the error
}
}
所以我们想用这个实现
void Class::SetPrivateMemberA() {
m_A = GetObject();
}
void Class::UseA() {
m_A.Method();
}
...我想到的问题是 GetObject() 仍然返回一个对象,一个 NULL 对象或其他。我喜欢不重复检查 null 并相信发送回的对象可用的想法,但为什么我不在第一个实现中这样做呢?
空对象模式的优点只是稍微增加了清理代码的信任吗?对于第二个实现,在调用 A.Method() 之前检查它是否不为 null 不是一个好习惯吗?
The main goal of the Null Object Pattern is to ensure that a usable object is provided to the client. So we want to replace the following code...
void Class::SetPrivateMemberA() {
m_A = GetObject();
}
void Class::UseA() {
if (m_A != null) {
m_A.Method();
} else {
// assert or log the error
}
}
...with this implementation:
void Class::SetPrivateMemberA() {
m_A = GetObject();
}
void Class::UseA() {
m_A.Method();
}
The problem I am thinking of is that GetObject() still returns an object, a NULL Object or otherwise. I like the idea of not checking for null repeatedly and trusting that the object sent back is usable, but why wouldn't I just do that in the first implementation?
Is the advantage of the Null Object pattern just a slight increase in trust to clean up code? With the second implementation, is it not still a good practice to check that it is not null before calling A.Method()?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你是对的,如果你确定你永远不会返回空值,只需在第一个实现中调用该方法之前跳过空值检查即可。同样,如果您确实需要在
UseA()
需要对 null 对象执行不同操作的情况下执行某些特殊操作,则无论如何您都需要显式检查 null 对象。然而,空对象模式真正有帮助的是那些并不重要的情况。以大多数观察者模式为例。如果您将观察者模式实现为只能有一个观察者的类的成员,并且想要向观察者宣布您的类做了某件事,那么观察者是否为 null 对于类来说并不重要。
这也通过空容器类进行了说明,这些类本质上是空对象模式:您只需返回一个空容器,而不是从查询中返回空容器。对于迭代容器的所有条目之类的事情,容器是否为空通常并不重要,因此消除空检查的需要使代码更易于维护/更具可读性。但是,如果您想要填充数据集的视图,您仍然需要显式显示不同的“无条目”。检查空容器。
为清楚起见进行编辑
一个问题是仅从调用站点查看它。与大多数设计模式一样,这需要包含双方才能充分利用。考虑一下:
vs
现在,你的调用代码,而不是看起来
可以是
You're correct that, if you're sure you're never returning nulls, just skip the null check before calling the method in your first implementation. Likewise, if you do need to do something special in the case that
UseA()
needs to do something differently on a null object, that you need to explicitly check for a null object anyway. However, what null object pattern really helps with is those situations where it doesn't really matter.Take, for example, most observer patterns. If you implement your observer pattern as a member of your class for which there can only be one observer, and want to announce to the observer that your class did something, it doesn't matter to the class whether the observer is null or not.
This is also illustrated with empty container classes, which are essentially the null object pattern: Instead of returning a null container from a query, you simply return an empty container. For things like iterating through all entries of a container, it often won't matter whether it's empty or not, so getting rid of the need of a null check makes the code more maintainable/more readable. However, if you want to populate a view of your data set, you still need to explicitly show a different "No entries." that checks for an empty container.
Edit for clarity
One problem is only looking at it from the call site. Like most design patterns, this needs to encompass both sides to be fully utilized. Consider:
vs
Now, your call code, instead of looking like
it can be
不。如果您知道 m_A 不为空,那么检查就是多余的;这是偏执编码的一个例子。它有什么危害?它使你的代码变得不必要的复杂化;它使得它更难阅读,更难调试。
No. If you know that m_A is not null, then the check is superfluous; it's an example of paranoid coding. What harm does it do? It complicates your code - unnecessarily; it makes it harder to read, harder to debug.