单例模式定义
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式使用场景
避免产生多个对象消耗过多的资源,或者某种类型的对象只应该有且只有一个。
对IO、数据库、网络、图片、SharePreference等的访问
需要定义大量的静态常量和静态方法,例如Utils类
唯一序列号生成的场合
需要一个共享访问点或者共享数据的场合,例如全局的计数器
Android中的SystemService就是通过单例的方式注册到系统当中
UML图
实现单例模式主要几个关键点
构造函数不对外开发,一般为private;
通过一个静态方法或者枚举返回单例类对象;
确保单例类的对象有且只有一个,尤其在多线程环境下;
确保单例类对象在反序列时不会重新构建对象;
单例模式的优点
当一个对象需要频繁地创建销毁时,单例模式可以减少内存开支,防止内存溢出。
当一个对象的产生需要比较多都资源时,如读取配置、产生其他依赖对象时,可以通过在应用启动时直接产生一个单例对象,然后用永久驻留内存的方法可以减少系统性能都开销。
可以避免对资源的多重占用,例如写文件操作,由于自由一个实例存在,避免了同时进行写操作。
单例模式可以在系统全局的访问点,优化和共享资源访问,例如,可设计一个单例类,辅助所有数据表的映射处理。
单例模式的缺点
单例模式一般没有接口,扩展很困难,除非修改代码。
代理对象如果持有Context,会引发内存泄露,最好传Application Context。
实现的方式:
1.饿汉模式
2.懒汉模式
3.双检锁 DCL 实现模式
4.静态内部类单例模式
5.枚举模式
6.使用容器实现单例模式
7.Kotlin中通过object关键字实现
单例的总结
饿汉:无法对instance实例进行延迟加载;
懒汉:在添加同步的情况下才能保证实例的唯一性,但导致性能缺陷;
双检锁DCL:JVM即使编译器的指令重排序,有时实例不会唯一,使用volatile可以改变这个情况;
静态内部类和枚举:在延迟加载 / 线程安全 / 性能优势更为突出。
参考书籍
《Android 源码设计模式解析与实战》
或者扫一扫关注我的公众号
领取专属 10元无门槛券
私享最新 技术干货