標籤:
本文已更新為2.0文法,具體查看:一葉單例模式
一、意圖
保證一個類公有一個執行個體。並提供一個訪問它的全域訪問點。
二、使用情境
1、使用情境
- 當類僅僅能有一個執行個體並且客戶能夠從一個眾所周知的訪問點訪問它時
- 當這個唯一執行個體應該是通過子類化可擴充的,並且客戶應該無需更改代碼就能使用一個擴充的執行個體時。
2、實現的重要三個步驟
- 私人化構造方法(Swift不支援)
- 使用一個靜態變數儲存執行個體的引用
- 提供一個全域的訪問方法
三、 Swift語言下的實現Swift語言不支援變數及方法的許可權,沒有辦法隱藏變數及方法,能夠任意直接建立一個執行個體。
單例的建立有非常多寫法,Swift支援僅僅有struct支援靜態變數。class不支援靜態變數。所以非常easy想到,在類的內部使用struct就能解決引用的儲存問題,代碼例如以下:
class SwiftSingleton { class var shared: SwiftSingleton { dispatch_once(&Inner.token) { Inner.instance = SwiftSingleton() } return Inner.instance! } struct Inner { static var instance: SwiftSingleton? static var token: dispatch_once_t = 0 } }
執行例如以下測試代碼。進行簡單測試:
class SwiftSingletonTest: XCTestCase { func testSingleton() { let singleton1 = SwiftSingleton.shared let singleton2 = SwiftSingleton.shared assert(singleton1 === singleton2, "pass") } }
執行結果,左側綠色對號代表執行通過:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZzFqdW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >
當中===在Swift中代表“等價於”,比較的是兩個變數或者常量的引用地址,僅僅能用於class的比較
在Swift中static類型變數會自己主動實現成延遲載入模式。也能夠更簡單的實現成例如以下:
class SwiftSingleton { class var shared: SwiftSingleton { return Inner.instance } struct Inner { static let instance = SwiftSingleton() }}
在全部語言中單例分為懶漢模式(延遲載入),餓漢模式,一般為了避免資源浪費,都喜歡實現成懶漢模式。即使用時在產生執行個體。在Swift語言中,因為statickeyword做了最佳化。自己主動實現了 延遲載入模式。所以上面的代碼實現的是懶漢模式而並不是餓漢模式
四、可能引起錯誤的實現class與struct一個很重要的差別:class:傳引用struct:傳值有部分人可能想通過struct來直接實現單例模式,因為struct傳遞時是傳的值。會造成記憶體中有多個拷貝。測試例如以下:
struct SwiftSingleton { var name: String = "1" static let shared = SwiftSingleton()}var single1 = SwiftSingleton.sharedvar single2 = SwiftSingleton.sharedsingle2.name = "2"println("------->\(single1.name)")println("------->\(single2.name)")
列印結果例如以下:
------->1------->2Program ended with exit code: 0
從上面能夠看到,通過struct下的實現,我們不能保證只有一個執行個體,這樣的實現是一個問題
著作權聲明:本文部落格原創文章。部落格,未經同意,不得轉載。
Swift辛格爾頓設計模式(SINGLETON)