前言:做IOS研发已经四年多了,一路走来发现一直泡在业务逻辑中,感觉还是要静下心总结一下相关的技术点,如有不对的地方欢迎指出,大牛勿喷。
一 什么是单利:
1.确保在程序运行过程中只创建一个对象实例
2.可以用于需要被多次广泛或者说多次使用的资源中
二 单利的创建 :
1.基础单利创建
为了隔绝外部的修改,要使用static静态变量
加锁是考虑到多线程调用时候的安全问题
同时也可以用GCD来创建单利,两者的效率是有很大的差异的,用dispatch_once的性能会提高很多,至于对比请参考这里
考虑到可能会不小心调用alloc,allocWithZone,copy,mutableCopy等方法,因此避免出现崩溃的情况,可以对以上几个方法进行重写,使代码的安全性更高.
至此一个完整的单利就写完了,既然单利写完了。
顺便附上Swift的写法
三 优缺点:
优点
1、提供了对唯一实例的受控访问。
2、由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。
3、因为单例模式的类控制了实例化的过程,所以类可以更加灵活修改实例化过程。
缺点
1、由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
2、单例类的职责过重,在一定程度上违背了“单一职责原则”。
四 单利存在的问题
1、单例模式实际上延长了对象的生命周期。那么就存在内存问题。因为这个对象在程序的整个生命都存在。所以当这个单例比较大的时候,总是hold住那么多内存,就需要考虑这件事了。另外,可能单例本身并不大,但是它如果强引用了另外的比较大的对象,也算是一个问题。别的对象因为单例对象不释放而不释放。当然这个问题也有一定的办法。比如对于一些可以重新加载的对象,在需要的时候加载,用完之后,单例对象就不再强引用,从而把原先hold住的对象释放掉。下次需要再加载回来。
2、在开发过程中,单例对象可能有一些属性,一般会放在init的时候创建和初始化。这样,比如如果单例A的m属性依赖于单例B,单例B的属性n依赖于单例A,初始化的时候就会出现死循环依赖。死在dispatch_once里。对于这种情况,最好的设计是在单例设计的时候,初始化的内容不要依赖于其他对象。如果实在要依赖,就不要让它形成环。实在会形成环或者无法控制,就采用异步初始化的方式。先过去,内容以后再填。内部需要做个标识,标识这个单例在造出来之后,不能立刻使用或者完整使用。
五 单利的销毁
1.将static dispatch_once_t onceToken; 这个拿到函数体外,使之成为全局的.
2.创建释放方法,并在方法中将onceToken置为0,因为这样,GCD才会认为它从未执行过.它默认为0.这样才能保证下次再次调用shareInstance的时候,再次创建对象.
3.单利对象release,并置为nil即可。
参考文献: