单例模式应该要属于比较简单的一种设计模式,正如它的名字一样,它只有一个实例,而且是在自己的类内部就产生,通过方法来提供给外部。
特点:
- 只有一个实例,且是private static
- 没有接口,不能继承
- 构造函数私有化
- 必须向整个系统系统这个实例,即getInstance方法应该是public static
组成:
- private static数据变量
- 私有构造函数
- 公共的getInstance方法()返回实例;
实现方式:
单例模式的实现方式有几种,但是基本的还是建立在懒汉式和饿汉式之上,这两个方式的区别就是类加载时,实例有没有初始化,即public static Singleton instance=?这个“?”是null还是new Singleton()。是null则是懒汉式,后者则是饿汉式。
除此之外,在getInstance方法中需要使用同步锁 synchronized防止多线程同时进入造成 instance 被多次实例化。这也产生了不同的单例实现模式如:双检锁、登记式和枚举。
1.懒汉式:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
//如果要想线程安全的化,在static后面可以加上synchronized关键字
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2.饿汉式:
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance() {
//没有加锁,执行效率会更高
return instance;
}
}
3.双检锁/双重校验锁(JDK1.5版本起):
public class Singleton {
private volatile static Singleton singleton;
//volatile关键字声明的变量或对象通常拥有和优化和(或)多线程相关的特殊属性。如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
//synchronized防止多线程同时进入造成 instance 被多次实例化。
if (singleton == null) {
singleton = new Singleton();
}
}
return singleton;
}
}
4.登记式/静态内部类:
Singleton类被装载时,instance不一定被初始化,因为SingletonHolder没有主动使用,即只有显示调用getInstance时(会装载类SingletonHolder),才会实例化instance
public class Singleton {
private static class SingletonHolder {
//适用于静态域的情况,对静态域使用延迟初始化
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
5.枚举(Jdk1.5版本起):
public enum Singleton {
INSTANCE; //适合反序列化创建对象时
public void Method() {
}
}