來源
單例模式的初衷是為了確保某些類的實例唯一,從而避免創(chuàng)建多個不必要的實例來節(jié)省資源、避免內(nèi)存溢出。
特點
- 實例唯一
- 必須自身創(chuàng)建這個實例
- 向其他類提供使用這個實例的接口
方法
- 私有構(gòu)造函數(shù)
- 創(chuàng)建私有靜態(tài)實例
- 創(chuàng)建公有靜態(tài)方法以獲取私有實例
使用地方
根據(jù)單例模式的特點和基本方法可以知道,單例模式一般用于一些全局應(yīng)用類、管理類和工具類,例如UIApplication、FileManager、Dao類等等。
常規(guī)用法
基本用法(餓漢式)
class SingleTon {
private init() {
}
private static let instance: SingleTon = SingleTon()
public static func getInstance() -> SingleTon {
return instance
}
}
這是單例模式最基本的用法,夠用,唯一的缺點就是實例沒調(diào)用就已經(jīng)初始化了。
如果實例化的時候還需要設(shè)置一些屬性的話,在swift中還可以用這樣的閉包形式:
class SingleTon {
private init() {
}
private static let instance = {
//set
return SingleTon()
}()
public static func getInstance() -> SingleTon {
return instance
}
}
基本用法(懶漢式)
class SingleTon {
private init() {
}
private static var instance: SingleTon? = nil
public static func getInstance() -> SingleTon {
if instance == nil {
instance = SingleTon()
}
return instance!
}
}
懶漢式是為了彌補餓漢式?jīng)]用就已經(jīng)存在的缺點,需要才用。這很好,但是在多線程下是很不安全的。假如有兩個線程同時訪問,將會創(chuàng)建兩個實例,顯然是不符合多線程下的實例唯一。
經(jīng)典用法(Double Check Lock)
class SingleTon {
private init() {
}
private static var instance: SingleTon? = nil
public static func getInstance() -> SingleTon {
if instance == nil {
objc_sync_enter(self)
if instance == nil {
instance = SingleTon()
}
objc_sync_exit(self)
}
return instance!
}
}
為了保持懶漢式的優(yōu)點,需要才用,使用了實例判空。同時為了保證多線程下的實例單一,加入了同步機制和二次判空。這樣即使多個線程同時訪問,都能保證實例唯一。這是最常見的用法之一。
經(jīng)典用法(內(nèi)部靜態(tài)類方法)
class SingleTon {
private init() {
}
public static func getInstance() -> SingleTon {
return SingleCreator.instance
}
class SingleCreator {
static let instance: SingleTon = SingleTon()
}
}
這種可以說是最得天獨厚的,利用classloader機制保證實例化時只有一個線程,絕對線程安全。同時,又能最大限度節(jié)省資源,確保單例唯一。是最最常用的單例模式
后記
綜上,無論任何語言最適合的還是DCL和靜態(tài)類形式!
沉舟側(cè)畔千帆過,病樹前頭萬木春
且行且珍惜