1、定义
保证一个类仅有一个实例(静态的),并提供一个访问它的全局访问点(getInstance())。
2、理解
国家虽然规定了只能生一个小孩的规定,但实际上你要生几个小孩,是你自己说了算,而不是国家说了算。
同样,对于一个类,要有几个实例是这个类本身说了算,而不是其他的类说了算(例如在main方法中。
好处:单例模式因为Singleton类封装它的唯一实例,这样它可以严格的控制客户怎样访问它以及何时访问它。简单说就是对唯一实例的受控访问(例如只能通过getInstance()方法去访问)。
代码:
class Singleton{
private static Singleton instance;
private Singleton(){
}
public static Singleton GetInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
public class Main {
public static void main(String [] args){
Singleton s1 = Singleton.GetInstance();
Singleton s2 = Singleton.GetInstance();
if(s1 == s2){
System.out.println("两个对象时相同的实例");
}
}
}
输出结果:
两个对象时相同的实例
3、多线程时的单例
问题:在多线程程序中,多个线程同时访问Singleton类,调用GetInstance()方法,会有可能造成创建多个实例。
解决方法:加锁
代码:
class Singleton{
private static Singleton instance;
private static Object syncRoot = new Object();
private Singleton(){
}
public static Singleton GetInstance(){
synchronized(syncRoot){
if(instance == null){
instance = new Singleton();
}
}
return instance;
}
}
缺点:每次调用GetInstance方法时都需要获取锁。
改进:
双重锁定,代码如下:
public static Singleton GetInstance(){
if(instance == null){
synchronized(syncRoot){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
4、静态初始化
饿汉式单例类:
这种静态初始化的方式是在自己被加载时就将自己实例化。
懒汉式单例类:
在第一次被引用时(例如new),才会将自己实例化。