2012-02-20 103 views
24

我是一個Java開發誰是開始把握依賴注射的全部功能,並且它突然對我說明白沒有辦法注入一個靜態方法。所以這讓我想到:是靜態方法DI反模式?靜態方法是DI反模式嗎?

更重要的是:如果我要擁抱依賴注入,這是否意味着我必須停止編碼靜態方法?我問,因爲沒有辦法嘲笑他們,並在單元測試期間注入模擬靜態,這對我來說是一個巨大的關閉。

編輯:我知道,一個共同的方式來「包裝」,並注入現有的靜態方法是這樣的:

public class Foo { 
    public static void bar() { ... } 
} 

public interface FooWrapper { 
    public void bar(); 
} 

public class FooWrapperImpl implements FooWrapper { 
    public void bar() { 
     return Foo.bar(); 
    } 
} 

...但我不問如何注入現有的靜態方法......如果我所有的代碼(從這個角度來看)都會接受DI的概念,我會問我是否應該停止寫下它們。

而且,我看到很多類似的相關問題,這一點,但無法找到問同樣的問題完全匹配。如果你發現這確實是另一個問題,請給我指出,我會自己解決這個問題(請不要只是關閉它!)。

回答

38

靜態方法適用於沒有關聯狀態的事物。一些工廠方法,「純功能」方法如Math.sin等都是完全可以接受的靜態方法。 java.lang.Mathjava.util.Collections有很多很好的可以接受的靜態方法的例子。

幸運的是,這些方法不需要依賴注入或與這些事物交互;他們並不是特別難以測試。他們沒有需要嘲笑或任何事情的依賴關係。另一方面,靜態或與靜態相關的靜態方法是完全邪惡的。 的反模式。

它經常有助於定義的方法爲無狀態(因此一個合法的靜態方法),當且僅當,它總是返回上等效的輸入等效輸出。這表明例如,數據庫查詢和文件系統I/O使得方法成爲有狀態的,因爲它們的輸出將根據文件系統或數據庫中的內容而變化。

+0

所以,如果我有一個叫做'嘶嘶聲()'方法,並在其中我做一個靜態調用到'Widget.buzz()'方法,它擊中一個數據庫,併發出各種變化,以我的本地文件系統,那麼如何測試'fizz()'而不用調用'Widget.buzz()'調用所有的巨大變化呢?我的觀點是,我認爲我應該停止完全編寫靜態方法,以便我可以在運行時注入正確的'Widget'對象(正常vs模擬),然後控制哪個「版本」的buzz()會觸發。思考? – IAmYourFaja 2012-02-20 20:08:13

+0

'Widget.buzz()'具有關聯的靜態狀態 - 數據庫和隱式的整個文件系統。這是邪惡的。 'fizz'可能需要一個'Widget'參數,並且你會嘲笑一個'Widget'來測試'fizz'。 – 2012-02-20 20:11:28

+0

啊,我從來沒有想過數據庫或文件系統是有狀態的。你用什麼標準來定義「有狀態」?我認爲這是我誤解的根源。 – IAmYourFaja 2012-02-20 20:15:50

2

不平凡的靜態方法與依賴注入兼容。簡單地讓他們成爲單身人士的實例方法。