这更像是一个风格问题,而不是“我遇到问题”。对于Null占位符对象(我使用正确的术语吗?),通常首选使用Singleton模式吗?为便于讨论,这是一个例子:
public interface Foo {
void myMethod();
}
public class RealFoo implements Foo {
void myMethod() { /* Do something productive */ }
}
public class MyUniverse {
public static void main(String args[]) {
Foo[] fooArray = new Foo[10];
// do something productive that might result in Null objects in the array
for (Foo f : fooArray) {
f.myMethod(); // I DONT WANT TO DO if (f != null) blah blah
}
}
}
好的,这就是我的情景,是否更喜欢做A或B?
// A
public class NullFoo implements Foo {
public NullFoo() {}
public void myMethod() { /* don't need to do anything */ }
}
// B
public class NullFoo implements Foo {
private static NullFoo _instance = null;
protected NullFoo() {}
public static NullFoo getInstance() {
if (_instance == null) _instance = new NullFoo();
return _instance;
}
public void myMethod() { /* don't need to do anything */ }
}
谢谢!我本能地认为B几乎总是优越但也许我错过了什么,所以我问......
答案 0 :(得分:3)
我会选择后者。在这方面,我可能会有一种趋势,但我并不认为单身人士本身就是邪恶的。如果一个类没有可变状态,那么单例就可以了。
我会将构造函数设为私有,但不受保护。此外,你的懒惰负载容易出现竞争;我只是在声明行(private static final Foo instance = new NullFoo();
)上实例化NullFoo。最后,不要忘记让类实际实现接口。 :)
答案 1 :(得分:1)
从虚拟机的角度来看,B解决方案会更好,因为java最多会实例化一个对象。
答案 2 :(得分:0)
好吧,有趣。不能说我曾经面对这个但是...
我建议是否要一致地使用实例(即它总是会做同样的事情)然后再用B.那样,你只有一个代表你的null对象的共享实例。这是一个节省空间的优化(而不是用NullFoos
混乱你的记忆。与Collections#emptyList
大致相同。
我必须说,就dsign而言,我不明白你为什么 //做一些有效的事情,可能会导致数组中的Null对象,这会占用{{1在Foo
中,然后将其替换为null。我确定你有理由。
答案 3 :(得分:-1)
我将单例实现为枚举。
enum NullFoo implements Foo{
INSTANCE{
// implement methods here
}
}
请参阅:Singleton > The Enum Way或阅读
第3项:
使用私有强制执行单例属性
构造函数或枚举类型
在Effective Java 2nd Ed by Joshua Bloch
答案 4 :(得分:-1)
我认为你不应该在这里使用接口。接口描述了一组操作,实现它的类需要支持。但是你正在使用NullFoo类来基本规避这个要求。
那么为什么不使用一个在myMethod实现中什么都不做的基类:
public class BaseFoo
{
public void myMethod()
{
// do nothing
}
}
public class DerivedFoo extends BaseFoo
{
public void myMethod()
{
// do actual work
}
}
或者,如果您的实际情况确实需要接口,那么请继续编写if (foo != null) ...
测试。