為什麼說Singleton 模式現在成為了反模式(Anti-Pattern)?
Why implementing a Singleton pattern in Java code is (sometimes) considered an anti-pattern in Java world?
現在, 有時會有一種觀點認為, Singleton 模式在Java code中是一個反模式。 為什麼這麼說呢?
依賴注入
其中的一個原因就是, 單例類不是那麼容易進行unit test, 你不能自由的控制例項化過程, 而且由於單例類的本質, 很容易造成在多個呼叫過程中的狀態跳躍。
目前依賴注入的原則已經非常流行, 每個類, 當它們需要進行某種功能時, 這些依賴的類和資源是注入進來的, 而不是通過單例類的accessor 方法, 因而, 測試類可以控制使用哪個依賴類的例項, 進而有機會根據需要來提供mock。
類似Spring 的開發框架會控制物件的生命週期, 並經常會提供一個單例類來使用, 但這些物件會由框架來負責注入到其他物件中, 因此基礎程式碼並不需要建立自己的單例類。
e.g. rather than this (for example)
例如, 與其創造這個類:
public class Portfolio {
private Calculator calc = Calculator.getCalculator();
}
你還不如通過注入來實現:
public class Portfolio { public Portfolio(Calculator c) { this.calc = c; } }
在這裡, Porfolio 物件並不需要了解到底有多少個Calculator 物件存在, 測試程式碼可以通過注入一個Dummy的Calculator 以方便測試。
併發
由於只有一個物件例項的原因, 在多執行緒方面的可選擇性也會受到限制。 對單例類的訪問會被通過synchronisation 等鎖的方式受到限制。如果能維持這些物件的多個例項, 那麼就可以根據執行的執行緒的多少來決定物件的例項數量, 從而增加程式碼的容量。
單一原則
單例模式違背的單一原則: 單例類自己控制了自己的建立和生命週期。