Singleton Design Pattern (單例設計模式)

--

Singleton 是一種設計模式並且適用於任何 OOP 的程式語言,其精神在於在於整個 App 中只會有一個實體存在,這也代表此實體被共享著。然而,Singleton 在 iOS 的設計中再常見不過了,舉凡 UIApplication、FileManager、UserDefaults 等都是。

Singleton 的生命週期從應用程式一啟動就開啟了它的人生,直到整個應用程式被消毀了,它才結束它的一生,而且,整個應用程式只會存在一個實例。當在考量要不要使用該設計模式時,應也要想想,此物件的生命週期是否也跟應用程式共存亡且只需要有一個呢?回頭想想 UIApplication、FileManager 和 UserDefaults 它們都具備了這樣的條件,再想想 Apple 為什麼要這樣設計,或許心裡就會明白了。這樣說,大家還不是很清楚,法蘭克就舉幾個適合不適合的例子來說明好了。

適合

  • 橫跨整個專案的全域變數。
  • 具唯一性的物件,例如處理字串或日期的小工具。
  • 具唯一性的環境配置檔。

不適合

  • UIView、UILabel 等類別除了違反單例的唯一性外,也違反了生命週期的特性。
  • API 所回傳的 Data Model,此類別的資料會是隨著每次請求所回應的資料而有所變動的。

以上對 Singleton 的設計模式已有初步了解了,文未也會討論 Singleton 是否符合多執行緒的安全議題?讓我們繼續看下去😀

▼產生一個 Single View Application 的專案

▼將專案名稱命名為 SingletonDemo

▼新增一個 DataAccessObject.swift 檔並撰寫 Singleton 的邏輯

如上建立了符合 Singleton 的類別,但法蘭克剛剛在前言有說道在 Swift3 之前為了符合執行緒安全的狀況下(也就是同時開啟多執行緒來取得該物件時,都要取到同一個物件),寫法會有些許的不同(可參考),但在 Swift3 Apple 大大的簡化了其寫法,說明如下。

如上說明,法蘭克使用了 static properties 的修飾字來定義變數,以符合執行緒安全(最後法蘭克會撰寫實例來驗證之),先來說明以上的程式碼範例。

第 5 行 => 透過 sharedInstance 變數來取得該類別的實例。宣告為 static 可直接透過物件 +「.」運算子來取得該實例。

第 25~ 27 行 => 初始化這個物件的建構子。在這邊宣告成 private(私有) 是因為只能在該類別裡生成,也就是目前的設計僅能讓 sharedInstance() 來生成,不能從外部去生成它。在這裡必須 override(覆寫) 掉父類別的建構子。

第 29~ 31 行 => 該物件銷毀的時侯會執行該區塊的程式碼,用來觀察物件被銷毀的時機點。

第 33~ 35 行 => 用來測試 Singleton 的方法。

▼在 ViewController的ViewDidLoad 方法下開啟三條執行緒來測試是否符合Singleton的設計模式

在 ViewDidLoad 加入以下程式碼後,啟動模擬器來測試看看:

執行的結果 console 會如下:

在這邊我們看到當呼叫 loadDatas() 時會執行 init,當再次呼叫該類的 loadDatas(),並不會再生成新的物件,這也就是 Singleton 的精神所在😀

如果您喜歡我的文章,請多按幾下「拍手」給我鼓勵,或是按「follow」讓我持續提供好文章給您。

--

--