Android 设计模式之 单例模式


之前做android 项目时,用的最多的就是设计模式,就是单例模式,用的时候,心里总有些疑问。今天呢,看了《Android 源码设计模式 解析与实战》,把自己的总结分享一下。

首先什么是单例模式?

单例模式:使用时,单例的对象必须保证只有一个实例存在,不予许自由构造对象。

那么单例模式的使用场景有哪些?

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

如何“单例”?

1.构造函数不对外开放,一般为private 。

2.通过一个静态方法或者枚举返回单例类对象。

3.确保单例类的对象在反序列化时不会重新构建对象。(下文会讲)

4.确保单例类对象有且只有一个,尤其是多线程下。

单例模式的分类

1.饿汉式


饿汉式

2.懒汉式


懒汉式

懒汉式与饿汉式的区别:

懒汉式:实名一个静态对象,并且在用户第一次调用getInstance 时进行初始化,优点:单例只有在使用时才会被实例化,一定程度上节约了资源。缺点:是第一次加载时需要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance 都进行同步,造成不必要的同步开销。一般不建议这么用。

饿汉式:是在声明静态对象时就已经初始化。

3.Double Check Lock (DCL)实现单例


DCL

DCL  介绍

DCL 在getInstance 方法中 对instance 进行两次判空:相信很多人对此都有些疑惑。为什么要判断两次,第一个判空是为了避免不必要的同步,第二层判断是为了在null 情况下创建实例。instance=new Singleton(); 语句看起来是有代码,单实际是一个原子操作,最终会被编译成多条汇编指令,大致做了三件事:

1.给Singleton 分配内存

2.调用Singleton 的构造函数,初始化成员字段

3.将instance 对象指向分配的内存空间(此时instance 就不是null 了)

但是jdk 1.5 以后java 编译器允许乱序执行 。所以执行顺序可能是1-3-2 或者 1-2-3.如果是前者先执行3 的话 切换到其他线程,instance 此时 已经是非空了,此线程就会直接取走instance ,直接使用,这样就回出错。DCL 失效。解决方法 SUN 官方已经给我们了。将instance 定义成 privatevolatilestatic Singleton instance =null: 即可

DCL 的优点,资源利用率高,第一次执行getInstance 时才会被实例化,效率高。缺点:第一次加载反应慢,也由于java 内存 模型的原因偶尔会失败,在高并发环境下,有一定缺陷,虽然发生概率很小。(很常用)

4.静态内部类单例模式


静态内部类单例

加载singleton 类时不会初始化instance 只有在调用getInstance 方法时,才会导致instance 被初始化,这个方法不仅能够确保线程安全,也能够保证 单例对象的唯一性,同时也延迟了单例的实例化,是推荐使用的单例模式实现方式。

5.枚举单例


枚举单例

它在任何情况下都是单例的,也是最简单的。在上述的几种单例模式下,都会有一种情况,它们会出现重新创建对象的情况,那就是反序列化。

要杜绝单例对象在反序列化时重新生成对象,那么必须加入如下方法:


反序列话方法

但是枚举就不必要加这个方法,因为反序列话它也不会生成新的实例。

6.使用容器模式实现单例


容器模式单例

将众多单例模式类型注入到一个统一的管理类中,在使用时根据key 对应类型的对象。这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了用户的使用成本,也对用户隐藏了具体实现,降低了耦合度。

个人公众号,Android 知识分享


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值