2

这更像是一个风格问题,而不是“我遇到麻烦的问题”。对于 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 几乎总是优越的,但也许我错过了什么,所以我问......

4

5 回答 5

3

我会选择后者。在这方面,我可能是一个趋势支持者,但我不认为单身人士天生就是邪恶的。如果一个类没有可变状态,那么单例就可以了。

不过,我会将构造函数设为私有,不受保护。此外,您的延迟加载很容易出现竞争;我只会在声明行 ( private static final Foo instance = new NullFoo();) 上实例化 NullFoo。最后,不要忘记让类实际实现接口。:)

于 2012-10-23T14:58:47.513 回答
1

从虚拟机的角度来看,B 方案会更好,因为 java 最多实例化一个对象。

于 2012-10-23T15:02:07.657 回答
0

嗯,很有趣。不能说我曾经遇到过这种情况,但是...

我建议如果要一致地使用该实例(即它总是做同样的事情)然后使用 B。这样,您只有一个表示您的空对象的共享实例。这是一种节省空间的优化(而不是使用NullFoos.Collections#emptyList

不过我必须说,就 dsign 而言,我不明白为什么你会//做一些有成效的事情,这可能会导致数组中出现 Null 对象,这些对象会占用Foo你的fooArray元素,然后用 null 替换它。我相信你有你的理由。

于 2012-10-23T15:05:15.753 回答
-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) ...测试。

于 2012-10-23T15:05:54.007 回答
-1

我将单例实现为枚举。

enum NullFoo implements Foo{
  INSTANCE{
    // implement methods here
  }
}

请参阅:Singleton > The Enum Way或阅读
Item 3: Enforce the singleton property with a private constructor or an enum type
in Effective Java 2nd Ed by Joshua Bloch

于 2012-10-23T15:02:54.903 回答