[翻譯] 單例(Singleton)
英文原文: https://sourcemaking.com/design_patterns/singleton
意圖
- 確保一個類只有一個實例,並提供一個訪問其實例的全局點;
- 封裝 “即時初始化” (just-in-time initialization)或 “首次使用時初始化” (initialization on first use)。
問題
應用需要一個且唯一一個對象的實例。而且,延遲初始化(lazy initialization)和全局訪問是必須的。
討論
使得具有單一實例對象的類負責創建、初始化、訪問和執行。聲明這個實例作為一個私有靜態數據成員。提供一個公共靜態成員函數封裝所有的初始化代碼,同時提供對這個實例的訪問。
任何時候,需要引用單一實例時,客戶端(使用類名和範圍精度操作符1)調用 accessor 函數。
只有滿足所有下面三個標準時,才應該考慮單例模式:
- 單個實例的所有權不能合理分配;
- 延遲初始化是可取的;
- 全局訪問未另行規定;
如果單個成員實例的所有權,何時以及如何初始化,全局訪問都不是問題,那麽單例模式將不足以令人感興趣。
單例模式可以擴展到支持訪問包含大量實例的具體應用。
“靜態成員函數訪問器”(static member function accessor)方法將不會支持 Singleton類的子類。如果需要子類,參考本書中的討論。
刪除一個Singleton類/實例是一個有意義的設計問題。可查看John Vlissides在討論中所說 "To Kill A Singleton" 。
結構
使得包含單一實例的類負責訪問和在第一次使用時初始化。這個單一實例是一個私有靜態屬性。而 accessor 函數是一個公共靜態方法。
示例
Singleton 模式確保這種類只有一個實例,並提供此實例的全局訪問點。它根據 singleton set 命名,singleton set 定義了一個只包含一個元素的集合。美國總統辦公室就是一個單例。美國憲法指定總統的選舉方式,限制了其任期,並定義了繼任的順序。所以,在任何給定時間,最多只有一個有效的總統。不管這個有效的總統的個人身份,這個標題 “美國總統” 是一個全局訪問點,識別在辦公室的那個人。
清單
- 在 “單一實例” 類中,定義一個私有靜態屬性。
- 在這個類中,定義一個公有靜態 accessor 函數。
- 在訪問器(accessor)函數中,進行 “延遲初始化”(在首次使用時創建)。
- 定義所有構造體為 protected 或 private 。
- 客戶端可能只能使用 accessor 函數來操控 Singleton 。
經驗法則
- Abstract Factory,Builder 和 Prototype 可以在它們實現中使用 Singleton 。
- Facade 對象常常是 Singletons,因為其只需要唯一一個 Facade 對象。
- 狀態對象常常是 Singletons 。
- Singleton 對於全局變量的優勢是當你使用 Singleton 時,你絕對確信實例的數目,而且你可以改變你的思維和管理任何數量的實例。
- Singleton 設計模式是最多被不恰當使用的模式之一。Singletons 只有在一個類必須只有一個實例,不能多,也不能少時,才能確定使用。設計者經常錯誤地使用 Singletons 替代全局變量。Singleton 出於意圖和目的是一個全局變量。Singleton 並沒有消除全局變量,它只是對其重命名。
- 什麽時候 Singleton 是不必要的?簡短的答案:大多數時候。長答案:當以引用的方式傳遞一個對象資源給需要它的對象更容易的時候,而不是讓對象全局訪問資源。對於 Singletons,真正的問題是它們給你一個好借口,不要仔細考慮一個對象的合適的可見性。發現在公開和保護對象之間合適的平衡,對於維護靈活性是非常重要的。
因為我們組有使用全局變量的壞習慣,所以我組織了關於 Singleton 的學習小組。接下來,我發現 Singletons 到處出現,而與全局變量相關的問題一個都沒有消失。對全局數據的問題的答案並不是把它變成 Singleton 。其答案是 “到底你們為什麽使用全局變量?” 改變名字不能改變問題。實際上,這樣,可能會使情況變壞,因為你有機會說,“哦,我沒有那樣做,我是這樣做的” —— 即使這樣和那樣是同一個事情。
代碼示例
Java | Singleton in Java | Singleton in Java |
C++ | Singleton in C++: Before and after | Singleton in C++ |
PHP | Singleton in PHP | |
Delphi | Singleton in Delphi | |
Python | Singleton in Python |
譯者註:
1、範圍精度操作符 - scope resolution operator,即 "::"
[翻譯] 單例(Singleton)