首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

Swift 單例模式三種實現方式:從 Objective-C 遷移指南

     編輯:關於C

背景:Objective-C 單例慣用寫法

+ (instancetype)sharedInstance {
    static dispatch_once_t once;
    static id instance = nil;
    dispatch_once(&once) { instance = [[self alloc] init]; };
    return instance;
}

Swift 版本一:全域常量(最簡單、推薦)

class Singleton1 {
    static let shared = Singleton1()   // 唯一實例,lazy + thread-safe
    private init() {}                  // 防止外部初始化
}

// 使用
let s1 = Singleton1.shared

優點:語法極簡、編譯器保證線程安全、延遲初始化。

Swift 版本二:巢狀結構體封裝(模擬 dispatch_once)

class Singleton2 {
    static var shared: Singleton2 {
        struct Holder {
            static let instance = Singleton2()
        }
        return Holder.instance
    }
    private init() {}
}

原理:結構體靜態常量首次存取時初始化,Swift 保證原子性。

Swift 版本三:dispatch_once 兼容寫法(舊專案遷移)

class Singleton3 {
    static var shared: Singleton3 {
        var instance: Singleton3?
        var token: Int = 0
        // Swift 3+ 已移除 dispatch_once,改用上述版本一/二
        // 此處僅示意 Objective-C 思維對應
        return instance!
    }
    private init() {}
}

注意:Swift 3 起 dispatch_once 已棄用,官方推薦靜態常量或巢狀型別方式。

關鍵點總結

特性版本一版本二OC dispatch_once
線程安全✅✅✅
延遲初始化✅✅✅
防外部實例化private initprivate initdispatch_once
推薦度⭐⭐⭐⭐⭐⭐⭐⭐⭐⚠️ 已棄用

進階:依賴注入替代單例

單例屬於「全域狀態」,難以測試與解耦。現代 Swift 偏好:

protocol Service { func doWork() }
class RealService: Service { ... }
class MockService: Service { ... }

// 使用時注入具體實現
func run(service: Service) { service.doWork() }
run(service: RealService()) // 生產
run(service: MockService()) // 測試

遷移檢查清單

  • 將 +sharedInstance 改為 static let shared。
  • 移除 dispatch_once,改用靜態常量。
  • 構造器標記 private。
  • 檢查是否有 init() 公開暴露,統一封鎖。
  • 考慮以協定+依賴注入取代單例,提升可測試性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved