2009-10-26 50 views

回答

13

幾天前回復了類似的問題here, mocking a Singleton。原文是針對C#.Net關於嘲笑單身人士的行爲,但仍應適用。

至於單身模式,它本身沒有任何問題 - 在許多情況下我們想集中邏輯和數據。但是,單例和靜態類之間存在很大差異。將您的單例構建爲一個靜態類,硬編碼將其實現傳遞給應用程序中的每個消費者 - 這使單元測試變得非常困難!

你想要做的是爲你的單例定義一個接口,爲你的消費者提供使用方法。反過來,您的消費者通過傳遞對實現類的引用(通常這是您的應用程序,或者如果您熟悉依賴注入\控制反轉,則是容器)。

這是一個框架,無論是誰實例化的消費者,這是負責確保一個和唯一一個實例浮動。從靜態類到接口引用真的不是那麼大的一個飛躍[如上面的鏈接所示],你只是失去了一個全局訪問實例的便利 - 我知道我知道,全局引用非常誘人,但盧克轉身回到黑暗面,你也可以!

一般來說,最佳實踐建議避免靜態引用,並鼓勵對接口進行編程。請記住,仍然可以將這些約束應用於單例模式。按照這些指導原則,你應該沒有問題的單元測試你的工作:)

希望這會有所幫助!


單身!=公共靜態類,而單==單個實例

1

I'm using the following pattern當我寫,我可以模擬一個基於靜態的單身人士。代碼是Java,但我認爲你會得到一個想法。這種方法的主要問題是,你必須放鬆構造函數來保護包(這種類型擊敗了一個真正的單例)。 作爲一個方面說明 - 代碼適用於嘲笑你的「靜態」代碼而不一定只是調用它的代碼

3

缺乏可測試性是經典Singleton模型(返回實例的靜態類方法)的主要缺點之一。就我而言,這足以證明可以重新設計任何使用Singletons來使用其他設計的代碼。

如果你絕對需要一個單一的實例,那麼依賴注入和寫入接口,正如johnny g所建議的那樣,絕對是要走的路。

0

如果你必須使用一個單身人士(並有理由這樣做......但我會盡可能避免它)。我會建議使用IOC容器來管理它。我不知道是否有一個德爾福或不。但是在Java中你可以使用Spring,在.NET中你可以使用Windsor/Castle。一個IOC容器可以容納Singleton並且可以註冊不同的測試實現。

這可能是一個太大的主題進入這個片段以外的地方。

1

我通常只使用Flyton對象或類似值對象的單身。查看IoC容器(如上所述)可能是處理共享對象比單例更好的方法。

考慮到在Smalltalk(其中很多這些模式的起源),真假都是有效的單身:)

+0

...關於Smalltalk中:是的,但真假是_so_可測試:) – mjn 2011-12-01 13:51:49

相關問題