前言
在看了其他语言的单例实现后,于是去查了一下swift单例的实现,发现swift单例实现及其的简单,简单到我对它正确性产生怀疑。我们首先简单了解一下单例模式。
单例规则
- 单例必须是唯一的,所以它才被称为单例。在一个应用程序的生命周期里,有且只有一个实例存在。单例的存在给我们提供了一个唯一的全局状态。比如我们熟悉的NSNotification,UIApplication和NSUserDefaults都是单例。
- 为了保持一个单例的唯一性,单例的构造器必须是私有的。这防止其他对象也能创建出单例类的实例。
- 为了确保单例在应用程序的整个生命周期是唯一的,它就必须是线程安全的。当你一想到并发肯定一阵恶心,简单来说,如果你写单例的方式是错误的,就有可能会有两个线程尝试在同一时间初始化同一个单例,这样你就有潜在的风险得到两个不同的单例。这就意味着我们需要用GCD的dispatch_once来确保初始化单例的代码在运行时只执行一次。
单例模式为什么存在
优点:
单例对象保证了只有一个实例的存在,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。 另一方面,全局单一对象也减少了不必要的对象创建和销毁动作提高了效率。
缺点:
- 全局共享可修改的状态:单例模式的副作用之一就是那些共享状态量在 app 的生命周期内都可能发生修改,而这些修改可能造成一些位置错误。更为糟糕的是因为作用域和生命周期的特性,这些问题还非常难定位。
- 依赖关系不明确:因为单例在全局都非常容易进行访问,这将是我们的代码变成所谓的 意大利面条 式的代码。单例与使用者的关系界限不明确,后期维护也非常麻烦。
- 难以追踪测试:因为单例模式与 app 拥有同样的生命周期而生命周期内进行的任意修改,所以无法确保一个干净的实例用于测试。
- 由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。
- 单例类的职责过重,在一定程度上违背了 “单一职责原则”。
单例的实现
在网上看了很多,目前最简单也是最有效的一种
全局变量方法(“单行单例”方法)
class SingletonOne {
static let sharedInstance = SingletonOne()
private init() {}
//切记私有化初始化方法,防止外部通过init直接创建实例。
}
当有继承其他类时,用override来重写init方法
可以通过下面的方式在获得实例前做些设置工作。
class SingletonTwo {
class var sharedInstance: SingletonTwo {
let instance = SingletonTwo()
//setup code
//...
return instance
}
}
以上就是我对swift单例的一些总结,关于正确性。这篇文章已经给出
http://www.cocoachina.com/swift/20151207/14584.html
参考资料
http://www.cocoachina.com/swift/20151207/14584.html
https://www.jb51.net/article/127687.htm