一、概念
单例模式是设计模式中最常见也最简单的一种设计模式,保证了在程序中只有一个实例存在并且能全局的访问到。比如在android实际APP 开发中用到的 账号信息对象管理, 数据库对象(SQLiteOpenHelper)等都会用到单例模式。下面针对一些例子分析一下我们在开发过程中应用单例模式需要注意的点。
二、作用
单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点
三、适用场景
1. 应用中某个实例对象需要频繁的被访问。
2. 应用中每次启动只会存在一个实例。如账号系统,数据库系统。
四、常用的使用方式
(1)懒汉式
- public class Singleton {
- /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */
- private static Singleton instance = null;
- /* 私有构造方法,防止被实例化 */
- private Singleton() {
- }
- /* 1:懒汉式,静态工程方法,创建实例 */
- public static Singleton getInstance() {
- if (instance == null) {
- instance = new Singleton();
- }
- return instance;
- }
- }
- Singleton.getInstance().method();
缺点: 线程不安全,在多线程中很容易出现不同步的情况,如在数据库对象进行的频繁读写操作时。
(2)加同步锁
优点:解决了线程不安全的问题。
缺点:效率有点低,每次调用实例都要判断同步锁
补充: 在Android源码中使用的该单例方法有:InputMethodManager,AccessibilityManager等都是使用这种单例模式
(3)双重检验锁
要优化(2)中因为每次调用实例都要判断同步锁的问题,很多人都使用下面的一种双重判断校验的办法
- /*3.双重锁定:只在第一次初始化的时候加上同步锁*/
- public static Singleton getInstance() {
- if (instance == null) {
- synchronized (Singleton.class) {
- if (instance == null) {
- instance = new Singleton();
- }
- }
- }
- return instance;
- }
-
- instance = new Singleton();
在JVM编译的过程中会出现指令重排的优化过程,这就会导致当 instance实际上还没初始化,就可能被分配了内存空间,也就是说会出现 instance !=null 但是又没初始化的情况,这样就会导致返回的 instance 不完整(可以参考:http://www.360doc.com/content/11/0810/12/1542811_139352888.shtml)。
调用:
- Singleton.getInstance().method();
缺点:不同平台编译过程中可能会存在严重安全隐患。
补充:在android图像开源项目Android-Universal-Image-Loader (https://github.com/nostra13/Android-Universal-Image-Loader)中使用的是这种方式。
(4)内部类的实现
内部类是一种好的实现方式,可以推荐使用一下:
- public class SingletonInner {
- /**
- * 内部类实现单例模式
- * 延迟加载,减少内存开销
- *
- * @author xuzhaohu
- *
- */
- private static class SingletonHolder {
- private static SingletonInner instance = new SingletonInner();
- }
- /**
- * 私有的构造函数
- */
- private SingletonInner() {
- }
- public static SingletonInner getInstance() {
- return SingletonHolder.instance;
- }
- protected void method() {
- System.out.println("SingletonInner");
- }
- }
调用:
- SingletonInner.getInstance().method();
(5)枚举的方法
这是网上很多人推荐的一种做法,但是貌似使用的不广泛,大家可以试试,
- /**
- * @function:单例模式枚举实现
- * @author xuzhaohu
- *
- */
- public enum SingletonEnum {
- /**
- * 1.从Java1.5开始支持;
- * 2.无偿提供序列化机制;
- * 3.绝对防止多次实例化,即使在面对复杂的序列化或者反射攻击的时候;
- */
- instance;
- private String others;
- SingletonEnum() {
- }
- public void method() {
- System.out.println("SingletonEnum");
- }
- public String getOthers() {
- return others;
- }
- public void setOthers(String others) {
- this.others = others;
- }
- }
调用:
- SingletonEnum.instance.method();