2012年11月27日 星期二

Singleton


目的

Ensure a class only has one instance, and provide a global point of access to it.
(確保類別只會有一個物體實體存在,並提供單一存取窗口。[1])

Singleton 是個非常簡單好懂的 pattern,上述的目的便非常清楚的述說其功用
它和全域變數一樣容易存取,並且可以保證只會有一個實體存在
全域變數則沒辦法作此保證

Singleton 的 UML Class Diagram:




















範例程式:

不論從 UML 還是範例程式都可以看出 Singleton 是 static variable and method 的應用
需要注意的是 C++ 版本的範例程式在 multi-thread 下,可能會產生問題
這問題需要利用 Double-check Locking 來解決
Objective-C 的版本便有考慮此問題

現在,若是需要衍生子類別
在 C++ 中,由於 static method 無法在子類別重新定義
因此只能透過父類別來實現
至於 Objective-C 的 class method 無此問題
因此可以十分簡單的達到此目的

範例程式(可衍生子類別):

在 C++ 版本中,我們是利用註冊表的方式並透過環境變數來決定需要產生的子類別
因此在程式執行時,並無法產生兩個不同的子類別
然而 Objective-C 版本則可以同時產生兩個不同的子類別
另外註冊表的方式會有一個最大缺點就是它不再是負責建立實體,而是先產生實體,然後決定要回傳哪一個,所以會有無用的物件存在記憶體中

Singleton 有不少衍生的問題被許多人詬病 [2]
除了 [2] 所提到的,Singleton pattern 其實和一般使用習慣不同
它並非透過 constructor 創造出來的,而是自己定義的 static method
Monostate pattern 則是和 Singleton 可以達到單一的 pattern
這 pattern 所強調的是單一狀態,而非 Singleton 強調單一實體
在這邊就不細講 Monostate,有興趣的人可以參考此篇:Singleton and Monostate

另外,Singleton 可以衍生到 dependency 的問題
如同 [2] 所述,Singleton 可以被 global access
因此,Singleton 在某種程度上可以減低 dependency
不過關於這問題,也有一些替代的 patterns 可以解決,例如:Dependency Injection
Dependency Injection 又是另一個故事,因此在這邊也不細談
只是讓大家了解有這東西

說了這麼多,究竟該不該用 Singleton?
小編認為能盡量少用就盡量少用,應該會有其他的替代方案可行
雖然這是很經典的 pattern,但是隨著時代演進,
某些 pattern 就會變得不太好而產生新的 pattern 取代之
Singleton 應該就是個顯而易見的例子

[1] "物件導向設計模式", Gamma, Johnson, Helm, Vlissides 著, 葉秉哲譯
[2] Why Singletons are Evil