我在SO評論中看到一些人認爲Singleton Pattern是一種反模式。我想知道爲什麼?爲什麼在Java代碼中實現單例模式(有時)被認爲是Java世界中的反模式?
回答
測試
一個原因是,單身不容易單元測試來處理。你無法控制實例化,並且它們本質上可能在調用時保持狀態。
由於這個原因,dependency injection的原則是受歡迎的。每個類都被注入(配置)它們需要運行的類(而不是通過單例訪問器派生),因此測試可以控制要使用哪些相關類實例(並在需要時提供模擬)。
像Spring這樣的框架將控制其對象的生命週期,並經常創建單例,但這些對象被框架注入到它們的依賴對象中。因此,代碼庫本身不會將對象視爲單例。
例如而比這(例如)
public class Portfolio {
private Calculator calc = Calculator.getCalculator();
}
你會注入計算器:
public class Portfolio {
public Portfolio(Calculator c) {
this.calc = c;
}
}
因此Portfolio
對象不知道如何存在Calculator
的許多實例/護理。測試可以注入一個虛擬Calculator
,使測試變得簡單。
併發
通過限制自己的對象的一個實例,用於穿線的選擇是有限的。訪問單例對象可能不得不被保護(例如,通過同步)。如果您可以維護這些對象的多個實例,那麼您可以根據您正在運行的線程定製實例數量,並增加代碼庫的併發能力。
那麼,如何使用單身的人對付「測試」和「併發「問題? – Pacerier
有些困難。像PowerMock這樣的工具可以提供重寫單例方法的手段,但它們是採用字節碼操作的複雜工具 –
我個人認爲,這違反了單一責任原則。 Singleton對象負責其目的和控制它們產生的實例的數量,我認爲這是錯誤的。
這就是爲什麼很多人將控制委託給工廠對象。
我認爲這隻會使[SRP的解釋]變得可疑。 –
以何種方式可疑? – MikePatel
可疑的是,這顯然不是單身人士的錯,但SRP的解釋表明它是。 SRP(或對此的解釋)似乎是有罪的一方。 –
還有,你可能對單身許多要求:
- 延遲初始化;
- 正確處置;
- 作用域(例如每個線程一個)。
通常情況下,還,你就會有一大堆單身的您的應用程序,以及辛格爾頓模式不允許可重用的代碼。因此,如果您想要爲所有單身人士實施所有這些擔憂,您將立即看到其反模式質量。
單身本身不一定是一個反模式,但他們只有幾個好處,當他們用錯了成爲一個反(這經常發生)。
通常情況下,單身是不是在所有的單身人士,而是「變相全局變量」。另外,當「只有一個實例」屬性實際上不是優勢時,通常會使用它們。 (同時多次執行錯誤的事實再次平衡)。
除此之外,他們可能會非常棘手時考慮多線程來實現(通常是做了錯事或低效率),和他們失去了他們的大部分好處,如果你想控制自己的實例。
如果你想控制實例化,你需要在程序早期的某個時候手動完成,但是你也可以創建一個普通對象的實例並傳遞它。
如果銷燬順序有任何問題,您也需要手動執行此操作。主函數中的一個自動對象更簡潔,更簡單。
[可變]單例是一種反模式的反模式。
重要的底層反模式是全局狀態(或環境狀態)。在全球化的狀態下,你的程序中有一個很大的依賴關係博客。這確實會影響測試,但這只是不良編程影響的一部分。
在那個層次感,加上辛格爾頓在簡單地聲明可變static
領域的複雜性完全沒有必要水平。
易變的static領域遭受同樣的確切問題,這是全球狀態。我看不出如何使用靜態字段比單例更好。有關於此的任何信息? –
@JuanMendes正如我說的,簡單的可變靜比單可變靜好,因爲他們沒有無謂的複雜性。 –
我應該檢討答案留下意見以前更好。 100%同意你的觀點。它基本上是全球狀態的委婉,所以稱之爲靜態字段至少不會試圖美化它。 –
奇怪。看起來Singleton的錯誤實現是一種「反模式」,而不是Singleton本身。
我想我們已經忘記了每個程序都必須從某個地方開始。每一個抽象都必須有一個具體的實現,並且最終每個依賴都將最終得到解決,否則你的應用程序將無法使用。
大多數DI框架允許實例化一個類作爲一個Singleton,它只是處理,對你。如果你選擇自己做DI,注入單身並不是問題。一個Singleton IS也可以測試,如果你使用DI來注入它,不會使一個類不穩定。
IMO,像所有其他模式在那裏(包括DI和IOC)它是一個工具。有時它適合,有時它不適合。
- 1. Java中的單例模式實現
- 2. 什麼可以被認爲是JMS架構中的反模式?
- 3. Builder模式的真實世界示例
- 4. 現實世界中應用命令模式的例子
- 5. 什麼真正的java源代碼實現橋接模式?
- 6. 爲什麼是代理模式的結構模式,爲什麼是狀態模式的行爲模式?
- 7. 在Actionscript 3中實現單例模式類的最佳方式是什麼?
- 8. 在現實世界中的設計模式
- 9. java中的阻塞模式是什麼
- 10. 爲什麼RDF被認爲是無模式的?
- 11. 什麼被認爲是最好的Java後綴樹實現?
- 12. 單例模式的實現
- 13. 在Ruby中實現單例模式
- 14. 根據維基百科,爲什麼「超級通話」被認爲是反模式?
- 15. 捕捉和拋出異常;爲什麼這被認爲是反模式
- 16. 什麼是操作DESede算法默認模式在Java中
- 17. 這是在java中ServiceLocator模式的有效實現嗎?
- 18. 在java代碼中查找帶有模式的單詞
- 19. 爲什麼現實世界中的Django模型級聯刪除失敗?
- 20. 在java代碼中獲取Logback模式
- 21. Java中的域事件模式實現?
- 22. 以MVC模式實現Java中的JFileChooser
- 23. 線程安全在Java中實現單例模式的有效方法?
- 24. Java中重複使用模式實例
- 25. 爲什麼這個代碼中的模式沒有詳盡?
- 26. 如何破壞我的世界世界(有Java錯誤代碼)
- 27. java中的模式匹配代碼
- 28. 將真實世界問題建模爲java類
- 29. Java Map反模式?
- 30. 如何在Java Swing中創建hello世界?我的代碼有什麼問題?
[Singleton設計模式:陷阱]的可能重複(http://stackoverflow.com/questions/1448393/singleton-design-pattern-pitfalls) – msw