日期:2014-05-20  浏览次数:20786 次

帮我看一下,下面这个单键模式为什么不对?
 //单键模式
 class A{
 private static A a;
 private void A(){
 }
 public static synchronized A  getA(A a){
 if(a == null){
 a = new A();
 }
 return a;
 }  
 }


public class fSingletonctory { 
A a = new A();
A b = new A();
System.out.println(a==b);
}


运行结果是false,为什么会是这样?如何改正?谢谢了


------最佳解决方案--------------------
单例模式有三种实现方式:

/**
 * 方法一:
 * 对象延迟初始化,第一次获取对象时进行初始化。但是每次获取对象都会进行同步。同步会给系统增加开销。
 */
public class Singleton {

private static Singleton uniqueInstance;

private Singleton(){}

public static synchronized Singleton getUniqueInstance(){
if(uniqueInstance==null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}


/**
 * 方法二:
 * 静态初始化器中创建单例,初始化类时即对对象初始化,即使当前没有用到对象。会增加初始化的开销。
 */
public class Singleton {
private static Singleton uniqueInstance= new Singleton();

private Singleton(){}

public static Singleton getUniqueInstance(){
return uniqueInstance;
}
}

/**
 * 方法三:
 * 双重检查加锁,对象延迟初始化,并且保证只有第一次获取对象时同步。
 */
public class SingletonDoubleCheckedLocking {
private volatile static SingletonDoubleCheckedLocking uniqueSingleton;

private SingletonDoubleCheckedLocking(){}

public SingletonDoubleCheckedLocking getInstance(){
if (uniqueSingleton==null) {
synchronized (SingletonDoubleCheckedLocking.class) {
if (uniqueSingleton==null) {
uniqueSingleton = new SingletonDoubleCheckedLocking();
}
}
}

return uniqueSingleton;
}
}

如果获取单例对象所增加的额外开销(如:初始化开销、同步开销)不是系统主要的负担的话。方法一和方法二均可以放心使用。

至于你的问题,首先构造方法应该是私有的。你的“private void A()” 不是构造方法,因为有返回值类型。
其次获取实例应该由程序中提供的全局访问点来获取。
------其他解决方案--------------------
亲,你的程序写的有问题。。。
private void A(){} 看清楚这个方法,它不是构造函数,应该是private A(){}
其次public static synchronized A  getA(A a){}方法一点意义也没有,将参数去掉。
完整代码。
public class A {
private static A a;
private A() {};

public static synchronized A getA() {
if (a == null) {
a = new A();
}
return a;
}
}

像这样使用
Demo37 a = Demo37.getA();
Demo37 b = Demo37.getA();
System.out.println(a ==b);

------其他解决方案--------------------
 private void A(){
 }
这个不是构造方法,楼上的人说了。
还有,你的构造方法都定义成private了,就是不让在创建实例的时候用new关键字。应该
A a = A.getA();//是的那个getA方法的参数可以不要
A b = A.getA();
这样看看a==b
------其他解决方案--------------------
楼上正解。单例模式么。都用getA()方法获得对象,这样a==b为true,因为引用了同一对象
------其他解决方案--------------------