Swift单例模式Singleton pattern的实现

单例是一个在 Cocoa 中很常用的模式了。对于一些希望能在全局方便访问的实例,或者在 app 的生命周期中只应该存在一个的对象,我们一般都会使用单例来存储和访问。
王巍 (@ONEVCAT)

单例可以保证的程序运行过程,一个类只有一个示例,而且该实例易于供外界访问。从而方便地控制了实例个数,并节约系统资源。

OC中的单例

OC中实现方式为利用GCD中的dispatch_once_t函数来确保代码只运行一次,保证线程上的安全性。

1
2
3
4
5
6
7
8
9
10
11
12
13
@implementation SomeManager

+ (id)sharedManager {
static SomeManager *staticManager = nil;
static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{
staticManager = [[self alloc] init];
});
return staticManager;
}

@end

调用方法

1
[SomeManager sharedManager];

Swift中实现方法

Swift可以无缝使用GCD,所以我们依然可以选择使用dispatch_once_t来实现。由于Swift还不支持不支持类变量,使用struct结构体来保存数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
class SingletonC {

class var sharedInstance : SingletonC {
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : SingletonC? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = SingletonC()
}
return Static.instance!
}
}

不过Swift中还有更简单的保证线程安全的方式let,上述方法简化后可以变成如下

1
2
3
4
5
6
7
8
class SingletonB {
class var sharedInstance : SingletonB {
struct Static {
static let instance : SingletonB = SingletonB()
}
return Static.instance
}
}

还有另一种更受大家欢迎,并被认为是当前的最佳实践的做法。由于现在 class 不支持存储式的 property,我们想要使用一个只存在一份的属性时,就只能将其定义在全局的 scope 中。

1
2
3
4
5
6
7
private let _SingletonASharedInstance = SingletonA()

class SingletonA {
class var sharedInstance : SingletonA {
return _SingletonASharedInstance
}
}

该方法调用为SingletonA.sharedInstance。如果想用SingletonA.sharedInstance()方式调用,则上述代码改为如下。

1
2
3
4
5
6
7
private let _SingletonASharedInstance = SingletonA()

class SingletonA {
class func sharedInstance : SingletonA {
return _SingletonASharedInstance
}
}

参考