Android开发中的单例模式应用详解
本篇章节讲解Android开发中的单例模式应用。分享给大家供大家参考,具体如下: 单例模式是应用最广的设计模式之一,在应用这种模式的时候,单例对象的类必须保证只有一个实例存在。许多时候,整个系统只需要拥有一个全局对象,这样有利于协调系统的整体行为。如一个应用中,应该只有ImageLoader实例,这个ImageLoader实例中又包含网络请求、缓存系统、线程池等,很耗资源,因此没有理由让他构造多个实例。这种不能自由构造对象的情况就是使用单例模式的场景。在Android系统中存在很多这种场景,比如最常用的 1.懒汉模式 懒汉模式是申明一个静态变量,并且在用户第一次调用getInstance时进行初始化,懒汉模式实现如下: public class Singleton { private static Singleton sInstance; private Singleton(){ } public static synchronized Singleton getInstance(){ if(sInstance == null){ sInstance = new Singleton(); } return sIntance; } }
2.Double Check Lock(DCL)实现单例 DCL方式实现单例模式的优点是既能够在需要的时候才初始化单例又能保证线程安全,且单例对象的初始化后调用getInstance不进行同步锁。实现如下: public class Singleton { private static Singleton sInstance; private Singleton(){} public static Singleton getInstance(){ if(sInstance == null){ synchronized(Singleton.class){ if(sInstance == null){ sInstance = new Singleton(); } } } return sInstance; } } 本程序的亮点在于 3.静态内部类单例模式 DCL虽然在一定程度上解决了资源消耗、多余的同步、线程安全等问题,但是它还是在某些情况下出现失效的问题。这个问题被才会被称为DCL双锁失效。静态内部类实现代码如下: public class Singleton{ private Singleton(){} public static Singleton getInstance(){ return SingletonHolder.sInstance; } private static class SingletonHolder { private static final Singleton sInstance = new Singleton(); } } 当第一次加载的时候Singleton类时,并不会初始化sInstance,只有第一次在调用Singleton的getS方法时才会导致sIn被初始化。因此第一次调用get方法会导致虚拟机加载SingletonHolder类,这种方法不但保证能够=线程安全们也能够,也能够保证单例对象的唯一性,同时也延迟了单例的实例化,。 4.枚举单例模式档 从Java1.5版本起,单元素枚举实现单例模式成为最佳的方法,实现代码如下 class Resource{ } public enum SomeThing { INSTANCE; private Resource instance; SomeThing() { instance = new Resource(); } public Resource getInstance() { return instance; } } 上面的类Resource是我们要应用单例模式的资源,具体可以表现为网络连接,数据库连接,线程池等等。 获取资源的方式很简单,只要 首先,在枚举中我们明确了构造方法限制为私有,在我们访问枚举实例时会执行构造方法,同时每个枚举实例都是static final类型的,也就表明只能被实例化一次。在调用构造方法时,我们的单例被实例化。 也就是说,因为enum中的实例被保证只会被实例化一次,所以我们的INSTANCE也被保证实例化一次。 可以看到,枚举实现单例还是比较简单的,除此之外我们再来看一下Enum这个类的声明: public abstract class Enum<E extends Enum<E>> implements Comparable<E>,Serializable 可以看到,枚举也提供了序列化机制。某些情况,比如我们要通过网络传输一个数据库连接的句柄,会提供很多帮助。 在上述的几种单例模式中,存在一种情况它们会出现重复创建对象的情况,那就是反序列化。通过序列化可以将一个单例的实例对象写到磁盘,然后再读回来,从而有效的获得一个实例。即使构造函数是私有的,反序列化时依然可以通过特殊的途径去创建类的一个新的实例,相当于调用该类的私有构造函数。反序列化操作提供了一个很特别的钩子函数,类中具有一个私有的、被实例化的方法readResolve,这个方法可以让开发人员控制对象的反序列化。上述几个示例中如果要杜绝对象下被反序列化中重新生成对象,那么需要加入如下方法: private Object readResolve() throws ObjectStreamException{ return sInstance; } 也就是在 5.使用容器实现单例模式 看看这种实现方式: public class SingletonManager { private static Map<String,Object> objMap = new HashMap<String,Object>(); private SingletonManager(); public static viud registerServuce(String key,Object instance){ if(!objMap.containsKey(key){ objMao.put(key,instance); } } public static Object getService(String key){ return objMap.get(key); } } 在程序初始化的时候,将多种单例类型注入到一个统一的管理类中,在使用时根据Key获取对象对应类型的独享,这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体的实现,降低了耦合度。 总结: 不管以哪种方式实现单例模式,它们的核心原理都是将构造函数私有化,并且通过静态方法获取一个唯一的实例,在获取这个的过程中必须保证线程安全、防止反序列化导致重新生成实例对象等问题。选择哪种方式取决于项目本身,如是否是复杂的并发环境、JDK版本过低、单例对象的资源消耗等。 更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》 希望本文所述对大家Android程序设计有所帮助。 您可能感兴趣的文章:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |