哪个是更好的单例实现?

时间:2012-09-04 01:44:10

标签: java design-patterns singleton

我正在研究Singleton模式的这两个实现:

 Class Customer {

int x;
static int count = 0;

private Customer()
{
    x = 1;
}

public static Customer GetCustomer()
{
    if(count==0)
    {
        count++;
        return new Customer();
    }
    else
    {
        return null;
    }
}
}

实现1,如果类已经实例化一次,则不调用构造函数。 OR

 Class Customer{

int x;
static int count = 0;
public Customer()
{
    if(count == 0)
    {
        x = 1;
        count++;
    }
    else
    {
        return;
    }
}

实现2,其中调用构造函数而不管天气如何,类已经实例化了一次或者没有。我在网上看了一个视频讲座,说实现2不是首选,因为它为构造函数分配了内存,尽管第二次没有实例化对象。我知道Java有自动垃圾收集,但只是想知道我在视频讲座中看到的内容是否相关。

2 个答案:

答案 0 :(得分:6)

有些人会说没有单身人士的实施是正确的,但我不是那个阵营。

人们经常倾向于使用它们(例如作为上帝的对象),但他们仍然有自己的位置(在我的看来,与这个答案几乎没有关系)。

出于这个答案的目的,我将假设你已经做出了正确的决定,需要一个单身人士,但我确实恳请你阅读它的潜在问题 - 可能有一个更好的方法来实现你的目的。


话虽如此,我不确定您的代码示例是否正确。单例应该返回一个且只有一个实例,如果需要则创建一个实例,如果没有,则为您提供先前创建的实例。

我没有看到您的第一个代码示例如何尊重该合同。它会在第一次调用时给你一个新的,然后它会在那之后给你 nothing

您的第二个代码示例似乎根本不会阻止多个对象

因此,如果这是他们提供的教育质量,我会仔细考虑非常是否要继续观看该视频。


在任何情况下,我更喜欢只构造一次的那个,因为你应该只有一个该类的对象。换句话说,正确同步的静态getMe()调用可以防止竞争条件允许创建多个Me对象,并且第一次创建新对象,在后续调用中返回相同的对象。

在伪代码中,这可能是:

class Me {
    private Me() {};

    private static Me *loner = NULL;

    public static synchronised Me *getMe() {
        if loner == NULL
            loner = new Me();
        return loner;
    }
}

答案 1 :(得分:0)

写一个正确的单身并不容易。你需要照顾竞争条件并防御反射攻击。例如,可以通过反射调用私有构造函数来创建另一个对象实例。 java中最简单,最安全的单例实现是使用枚举:

完成的
enum Singleton {
    INSTANCE;
}

那是因为枚举常量被JLS加速为单例(JLS的第8.9节):

  

枚举类型没有除其枚举常量定义的实例之外的其他实例。