iOS之单例模式初探

iOS之单例模式初探

最近项目开发中喜欢使用单例,因为它数据共享,初始化也都由单例类内部管理,我调用就好了,师父看一眼我的代码之后说我单例滥用了,确实是滥用了。因为在这次项目开发中我把每一个模块的网络管理类都设置为单例,虽然这个管理类与单例类似的是全局只初始化一次,但是这个管理类只是在固定的类中使用,并不适用于全局,从这一点来说,那么这个单例就是是没有必要的。

版本初步上线后来总结一下单例。

接下来将从以下几个方面来讨论单例:

1.什么是单例模式?

2.怎么创建一个单例?

3.什么时候需要使用单例模式?

4.单例模式的优点与缺点?

1.什么是单例模式?

单例模式确保指定的类中只存在一个实例对象,并且可以全局访问那个实例。

2.怎么创建一个单例?

注:本文是在ARC环境下,结合GCD的dispatch_once函数实现单例,除了结合GCD来创建单例外,还可以通过其他形式来创建,本文暂时没有进行说明。

单例创建代码如下图,通过类方法sharedManager获取AlipayPayManager实例对象。

这里写图片描述

图 1-1

对dispatch_once函数的理解?

dispatch_once函数有两个参数,第一个参数token用来保证执行一次,第二个参数是要执行一次的任务block。

需要注意的一点是dispatch_once函数是在给定的token下仅执行一次,每次调用函数时传入的token必须相同,所以因此常将token标记声明在static或者global作用域中。

sharedManager方法是线程安全的,因为首次调用sharedManager该函数时,必然会执行dispatch_once块中的代码,并且dispatch_once块中的代码在给定的token下仅执行一次。

单例验证:

每次调用sharedManager方法时,获取到AlipayPayManager的对象是相同的,但是当我们调用alloc或者copy方法来构造对象时,依然会创建新的实例,通过打印对象的内存地址可以验证。

这里写图片描述

图 1-2

根据图1-2可以可知,通过单例创建的对象与调用alloc创建的对象内存地址不相同,即创建出了不同的对象,也就是说我们通过图1-1中sharedManager方法创建的单例并不安全。

那我们应该怎么处理上述问题呢?

当我们调用alloc方法时,oc内部会调用allocWithZone这个方法来申请内存,我们覆写这个方法,然后在这个方法中调用shareInstance方法返回单例对象,这样就可以达到我们的目的。拷贝对象也是同样的原理,覆写copyWithZone方法,然后在这个方法中调用shareInstance方法返回单例对象。

修改后的代码如图:

这里写图片描述
图 1-3

注意:在图1-3中的shareManager方法中,不是使用alloc方法,而是调用[[super allocWithZone:NULL] init]方法,这是为什么?

因为调用alloc方法时,alloc会调用allocWithZone方法,我们在重写allocWithZone时又调用了shareManager,这样就导致了一个死循环,程序会直接崩溃,所以为了避免死循环,我们直接借用父类处理底层内存分配。

我们优化单例写法之后,再次来验证一下在alloc,copy,shareManager中创建的对象实例是否为相同的对象,验证结果如下图1-4,根据内存地址来看,无论我们是通过shareManager、alloc、copy创建出来的对象都是相同的,保证了对象的唯一性。

这里写图片描述

图1-4

3.什么时候需要使用单例?

1)资源共享且只需要初始化1次。比如说一般的工具类。例如:网络数据请求,数据库数据请求类,登录控制类等。

2)类间需要数据共享,但又不想让类间发生关联关系,这时可以使用单例。

4.单例模式的优点与缺点?

优点:

1)单例确保系统内存中只存在一个实例对象,对于一些频繁创建和销毁的对象来说,单例节省了系统资源。

2)单例使程序更加灵活,因为类控制了对象的实例化过程,所以如果需要修改实例化过程时,可以统一在单例类创建中修改。

缺点

1)单例使用不恰当导致单例滥用,会占用内存,因为单例一旦创建,在程序整个生命周期内是不会释放的(除非手动把它release掉)。

2)上述中的单例是结合dispatch_once来使用,保证单例对象只会被创建一次。如果不小心销毁了单例,再调用单例生成方法是不会再创建的。

注:单例可能被销毁的情况:
1.手动释放单例创建出的实例对象;
2.更换参数token,重新创建了单例的实例对象。

单例总结到此结束,有问题的话后续再更新。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值