为什么单例模式是邪恶的(译)
原文鏈接:http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx
雖然這篇文章不是我寫的,但我完全同意文章中的觀點(diǎn)。Brian Button可能是我所知道的最有才的人之一。我相信他會(huì)喜歡你們的反饋的。
1、單例模式經(jīng)常被用來為某些服務(wù)提供一個(gè)全局訪問點(diǎn)
沒錯(cuò),是可以這么做,但代價(jià)是什么呢?眾所周知,單例模式為你的應(yīng)用程序中的某些服務(wù)提供全局訪問點(diǎn),這樣你就不必到處傳遞一個(gè)該服務(wù)的引用。這和一個(gè)全局變量有什么區(qū)別呢?(記住,全局變量是不好的,不是嗎?)最終會(huì)發(fā)生的事情便是你設(shè)計(jì)中的依賴關(guān)系是隱藏在代碼中的,這種依賴關(guān)系不能夠通過檢查你的類和方法的接口所見。你必須檢查代碼以便準(zhǔn)確地知道你的類中都用了哪些其他對(duì)象。這可能會(huì)是不清楚的(譯者注:不知道是不是這么翻譯,原文:This is less clear than it could be)。沖動(dòng)地創(chuàng)建一個(gè)全局性的東西來避免把其傳來傳去是你設(shè)計(jì)中的異味,這不是全局變量或者單例的功能。如果你更仔細(xì)地檢查你的設(shè)計(jì),你幾乎總是能想到一種不必把“流浪數(shù)據(jù)”四處傳遞到每個(gè)對(duì)象和方法的更好的設(shè)計(jì)。
2、單例模式允許你限制你所創(chuàng)建的對(duì)象的數(shù)量
這也是對(duì)的,但是現(xiàn)在你混合了兩個(gè)不同的職責(zé)到同一個(gè)類中了,這是違反了單一職責(zé)原則的。一個(gè)類不應(yīng)該關(guān)心它是否是一個(gè)單例,它應(yīng)該僅僅關(guān)心它的業(yè)務(wù)職責(zé)。如果你想限制某些類的實(shí)例化能力,創(chuàng)建一個(gè)封裝了創(chuàng)建并且如你所愿的那樣限制創(chuàng)建能力的工廠或者對(duì)象生成器,這樣創(chuàng)建職責(zé)便從業(yè)務(wù)實(shí)體職責(zé)中劃分出來了。
3、單例模式促進(jìn)了類之間的緊耦合
使代碼是可測(cè)試的一個(gè)基本屬性便是它和其周圍環(huán)境是松耦合的。這個(gè)屬性允許你在測(cè)試過程中為了實(shí)現(xiàn)特定的測(cè)試目標(biāo)(想想模擬對(duì)象)替換備用的合作者。單例模式把單例對(duì)象的確切類型緊耦合在一起,喪失了使用多態(tài)來替換的機(jī)會(huì)。一個(gè)更好的選擇,如上面第一點(diǎn)所討論到的,便是改變你的設(shè)計(jì)以便允許你傳遞對(duì)象的引用到你的類和方法中,這樣可以減輕上述的耦合問題。
4、單例模式在程序的持續(xù)過程中一直保存著上一次的狀態(tài)
持久狀態(tài)是單元測(cè)試的敵人。讓單元測(cè)試有效的事情之一便是每個(gè)測(cè)試必須獨(dú)立于其他所有測(cè)試。如果不是這樣,那么測(cè)試運(yùn)行的順序會(huì)影響到測(cè)試的結(jié)果。這可能會(huì)導(dǎo)致測(cè)試在不應(yīng)該失敗的地方失敗,甚至更壞的事情是僅僅因?yàn)闇y(cè)試的運(yùn)行順序?qū)е聹y(cè)試通過。這可能會(huì)隱藏住bugs并且是邪惡的。防止?fàn)顟B(tài)從一個(gè)測(cè)試攜帶到另一個(gè)測(cè)試的一個(gè)很好辦法便是避免使用靜態(tài)變量。單例模式,就其本質(zhì)而言,依賴于在一個(gè)靜態(tài)變量中保存著一個(gè)實(shí)例。這是測(cè)試依賴的一個(gè)挑戰(zhàn),可以通過傳遞對(duì)象的引用到你的類和方法中來避免。
希望這篇文章或多或少地闡釋了我對(duì)于單例模式觀點(diǎn)。我有一個(gè)從google或者其他地方找到的一個(gè)小鏈接集,包括Jim Hyslop和Herb Sutter,他們同樣分享了這些觀點(diǎn)。如果你喜歡他們那么讓我知道吧。
轉(zhuǎn)載于:https://www.cnblogs.com/shower/p/3738754.html
總結(jié)
以上是生活随笔為你收集整理的为什么单例模式是邪恶的(译)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 18.用两个栈实现队列[2StacksT
- 下一篇: NGUI中UILabel使用url标签的