设计模式之单例模式
单例模式:某个类只能生产一个实例,该类提供了一个全局访问点供外部获取该实例。
懒汉式单例
public class SingleMode1 {
/**
* 一来先进行实例化
*/
private static final SingleMode1 instance = new SingleMode1();
/**
* 私有构造方法
*/
private SingleMode1() {
}
/**
* 共有获取实例的方法
*
* @return
*/
public static SingleMode1 getInstance() {
return instance;
}
}
优点:线程安全、获取实例快
缺点:资源利用率不高,有可能用不到实例
懒汉式单例
public class SingleMode2 {
/**
* 先不进行初始化
*/
private static SingleMode2 instance = null;
/**
* 私有构造方法
*/
private SingleMode2() {
}
/**
* 获取实例的时候进行初始化
*
* @return
*/
public static SingleMode2 getInstance() {
if (instance == null) {
instance = new SingleMode2();
}
return instance;
}
}
存在问题:在多线程下可能创建多个实例,例如:A线程和B线程同时获取实例时,A已经进入初始化阶段,B也判断到instance==null,两个线程都进行了初始化实例。
加强版懒汉式
public class SingleMode3 {
/**
* volatile 可以产生内存屏障,防止指令重排序 保证执行步骤 1.new SingleMode3()产生一个地址值 2.把地址值赋给instance 3.初始化对象
*/
private static volatile SingleMode3 instance = null;
/**
* 私有构造方法
*/
private SingleMode3() {
}
/**
* 获取实例的时候进行初始化
*
* @return
*/
public static SingleMode3 getInstance() {
if (instance == null) {
synchronized (SingleMode3.class) {
//double check
if (instance == null) {
//不是原子操作
instance = new SingleMode3();
}
}
}
return instance;
}
}
缺点:因为锁,所有效率低
静态内部类单例
public class SingleMode4 {
static class T {
public static SingleMode4 instance = null;
}
private SingleMode4() {
}
public static SingleMode4 getInstance() {
return T.instance;
}
}
静态代码块单例
public class SingleMode5 {
private static SingleMode5 instance;
static {
instance = new SingleMode5();
}
private SingleMode5() {
}
public static SingleMode5 getInstance() {
return instance;
}
}
枚举单例
public enum SingleMode6 {
INSTANCE;
private SingleMode6() {
}
public static SingleMode6 getInstance() {
return INSTANCE;
}
}
破坏单例模式
单例会被攻击:clone、序列化、反射
枚举类什么攻击都攻击不了。枚举类型可以预防反射,在源代码中对枚举类型做了判断,如果反射会抛出异常。