单例模式
一,定义确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例
二,目的避免产生多个对象消耗过多的资源。对象被共享,可以节省内存,并加快对象访问速度
三,关键点
3.1 构造函数不对外开放,一般为Private
3.2 通过一个静态方法或者枚举,返回单例类对象
3.3 确保单例类的对象有且只有一个,尤其是在多线程环境下
3.4 确保单例类在反序列化时不会重新构建对象时,实现方式
四,实现方式
4.1 懒汉模式
public class SingleTon {
private static SingleTon mSingleTonInstance;
private SingleTon(){
}
public static synchronized SingleTon getInstance(){
if (mSingleTonInstance == null) {
mSingleTonInstance = new SingleTon();
}
return mSingleTonInstance;
}
}
优点:单例只有在使用时才会被实例化
缺点:第一次加载时需要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance都进行同步,造成不必要的同步开销
不建议使用
4.2 Double Check Lock(DCL)实现单例
public class SingleTonDCL {
// private static SingleTonDCL mSingleTonDCLInstance;
private volatile static SingleTonDCL mSingleTonDCLInstance;
private SingleTonDCL(){
}
public static SingleTonDCL getInstance(){
if (mSingleTonDCLInstance == null) {
synchronized (SingleTonDCL.class) {
if (mSingleTonDCLInstance == null) {
/**
* 下面这行代码,做了三件事情
* 1,给SingleTonDCL的实例分配内存
* 2,调用SingleTonDCL()的构造函数,初始化成员字段
* 3,将mSingleTonDCLInstance对象指向分配的内存空间(此时mSingleTonDCLInstance不再是null)
* ===============================================================================
* 因为JVM编译器允许处理器乱序执行,以及JDK1.5之前JVM中Cache、寄存器到主内存会写顺序的规定,上面2和3的执行顺序是无法保证的,
* 所以需要使用volatile关键字
*/
mSingleTonDCLInstance = new SingleTonDCL();
}
}
}
return mSingleTonDCLInstance;
}
}
既能够在需要时才初始化单例,又能保证线程安全,且在单例对象初始化后调用getInstance不进行同步锁
优点:资源利用率高,第一次执行getInstance时单例对象才会被实例化,效率高
缺点:第一次加载时反应稍慢,也由于Java内存模型的原因偶尔失败,在高并发环境下也有一定的缺陷,虽然发生概率很小
4.3 静态内部类单例模式
/**
* 静态内部类单例模式
* Created by liubo on 2017/9/7.
*/
public class SingleTonStaticInner {
private static SingleTonStaticInner mSingleTonStaticInner;
private SingleTonStaticInner(){
}
public static SingleTonStaticInner getInstance(){
return SingleTonStaticInnerHolder.mSingleTonStaticInner;
}
/**
* 静态内部类
*/
private static class SingleTonStaticInnerHolder{
private static final SingleTonStaticInner mSingleTonStaticInner = new SingleTonStaticInner();
}
}
上面的实现方式中,为了防止在反序列的时候重新生成对象,需要加入如下方法
private Object readResolve() throws ObjectStreamException{
return mInstance;
}
4.4 枚举
public enum SingleTonEnum {
INSTANCE;
public void doSomething(){
Log.d("Demo", "we can do what we want");
}
}
================================================================
Kotlin
class SingleTon private constructor() {
var value: SingleTon? = null
private object Builder {
val INSTANCE = SingleTon()
}
companion object Factory {
fun getInstance(): SingleTon {
return Builder.INSTANCE
}
}
}