我正在研究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有自动垃圾收集,但只是想知道我在视频讲座中看到的内容是否相关。
答案 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节):
枚举类型没有除其枚举常量定义的实例之外的其他实例。