单例模式

本文链接地址

单例模式

一,定义确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例

二,目的避免产生多个对象消耗过多的资源。对象被共享,可以节省内存,并加快对象访问速度

三,关键点

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
        }
    }
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值