单列模式的定义:
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.在计算机系统中,线程池,缓存,日志对象,对话框等常被设计成单例
单例模式的特点:
1.单例类智能有一个实例.
2.单例类必须自己创建自己的唯一实例.
3.单例类必须给其他对象提供这一实例.
实现单列的5种方式
懒汉式:默认不会实例化,第一次使用的时候实例化.(可能会由有线程安全问题)
1. 双重检查,已解决线程安全问题【推荐使用】
public class Singleton4 {
private static volatile Singleton4 singleton;
private Singleton4() {
}
public static Singleton4 getInstance() {
if (singleton == null) {
synchronized (Singleton4.class) {
if (singleton == null) {
singleton = new Singleton4();
}
}
}
return singleton;
}
}
2.静态内部类 【推荐使用】
public class Singleton5 {
private Singleton5() {
}
// 静态内部类
public static class Singleton5Instance {
private static final Singleton5 INSTANCE = new Singleton5();
}
public static Singleton5 getInstance() {
return Singleton5Instance.INSTANCE;
}
}
饿汉式 : 默认实例化 (类加载的时候实例化 无线程安全问题)
1.静态常量【可用】
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
2.静态代码块【可用】
public class Singleton2 {
private static Singleton2 INSTANCE;
private Singleton2() { }
static {
INSTANCE = new Singleton2();
}
public static Singleton2 getInstance() {
return INSTANCE;
}
}
3.枚举【推荐使用】
public class Singleton6 {
public Singleton6() {
}
public static Singleton6 getInstance() {
return SingletonEnum.INSTANCE.getSingleton();
}
private enum SingletonEnum {
INSTANCE;
private Singleton6 singleton;
SingletonEnum() {
singleton = new Singleton6();
}
private Singleton6 getSingleton() {
return singleton;
}
}
}
单例模式的破坏以及解决办法 (反射/反序列化)
除枚举外,其他的方法都可以通过反射的方式破坏单例模式 反射是通过调用构造方法生成新的对象,如果想要阻止单例被破坏,可以在构造方法中进行判断.
private Singleton4() {
if (singleton != null) {
throw new RuntimeException("实例已经存在,请通过 getInstance()方法获取");
}
}
如果单例类实现了Serializable, 就可以通过反序列化破坏单例.解决办法是在单例类中添加反序列化方法readResolve
public class Singleton5 {
private Singleton5() {
}
// 静态内部类
public static class Singleton5Instance {
private static final Singleton5 INSTANCE = new Singleton5();
}
public static Singleton5 getInstance() {
return Singleton5Instance.INSTANCE;
}
// 防止反序列化破坏单例模式
public Object readResolve() {
return Singleton5Instance.INSTANCE;
}
}
添加readResolve 方法,方法中返回实例的逻辑与单例类提供的获取实例的逻辑一模一样.