2011-06-09 136 views
5

我審查代碼具有很多語句的是這樣的:服務定位與依賴注入

private SomeInterface x = Locator.getInstance(SomeInterface.class) 

我希望像

private SomeInterface x; 

@Inject 
public Consumer(SomeInterface x){ // constructor 
    this.x = x; 
} 

有什麼問題與第一種方法?好的,依賴關係並不那麼明顯,但實現可以通過配置Locator輕鬆地進行交換。

+0

https://steveschols.wordpress.com/2012/05/14/dependency-injection-vs-service-locator/#comment-539 – 2016-06-15 12:57:23

回答

6

第一個例子: X = Locator.getInstance(SomeInterface.class)是看起來像Service Locator模式,並http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx檢查這篇文章中說,服務定位器是一個反模式,應該避免

而爲第二次使用它的所有罰款我喜歡構造函數注入,其順利罰款實施。但我想不使用Attributes(Java中的annotanitons?)導致任何時候我可能想更改我正在使用的DI容器,我不想從所有類中刪除屬性。

+2

'@ Inject'已標準化Java [JSR-330](http://www.jcp.org/en/jsr/detail?id=330) – deamon 2011-06-09 11:42:39

+0

@deamon我認爲這只是CrazyBob的DI的註釋。不知道它被接受爲語言標準。謝謝(你的)信息。 – adt 2011-06-09 12:32:11

9

Martin Fowler的寫了article on DI versus Locators

對於DI:

  • 更輕鬆地確定相關性的組件已 - 看 構造。
  • 組件不依賴於服務定位器,因此如果組件與 使用不同的框架,則不存在 問題。
  • DI可以使測試更加簡單,但良好的服務定位器機制將 化妝磕碰同樣可行

反對DI:

  • 難以調試和理解。
  • 一旦配置了 ,組件就無法從噴油器請求額外的服務。

我個人不認爲有什麼本質壞的第一定位器爲基礎的方法 - 我想,雖然不DI規範這一點,所以如果它是可用的,我會用它。所有好的想法往往最終都會在某個時候成爲框架,所以這裏就發生了一些事情。加上DI,您可以利用其他註釋,範圍等,而無需推出自己的代碼。而且你的項目使用更好的IMO代碼越少。我會留下最後一句話福勒雖然:

服務定位和 依賴注入之間的選擇比從應用程序中使用 服務分離 服務配置的原則不太重要 。

1

沒有什麼「錯誤」這樣的服務定位器模式,

在這種特殊情況下,有利於DI的一個主要理由是可測性。

毫無疑問,DI允許更好的單元測試。 Locator上的靜態getInstance方法使得單獨測試更加困難。

+0

除了單元測試,還有更多。 Mark Seemann已經非常清楚地描述了這一點:http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx。 – Steven 2011-06-09 11:50:51

+2

想要避免這些類型的哲學討論:)「反模式」是一個過度使用的聲明恕我直言。我個人也贊成DI,但在代碼審查期間我不會將其標記爲反模式。 – ddewaele 2011-06-09 11:59:37

+0

幾年前,我在項目中引入了IoC(以服務定位器模式的形式),以允許該團隊開始編寫測試。這是一個從根本上無法測試的好開始。但是現在,超過兩年後,將這種模式遍佈全球而不是使用直接投資是一個真正的痛苦。所以對我來說這不是哲學了。我去過那裏,我經歷過,這都是我的錯。現在,我儘可能地尖叫,以幫助別人解決我犯的錯誤。 – Steven 2011-06-09 12:27:57

2

Service locator模式使用稱爲「服務定位器」的中央註冊表,根據請求返回執行特定任務所需的信息。

這些服務定位器設計模式中最糟糕的方面:

  • 東西放置在註冊表中與 關於該系統的其餘部分有效黑匣子。這使得難以檢測並且從其錯誤中恢復,並且可能使得整個系統不太可靠。

  • 註冊表必須是唯一的,這可能會使其成爲並行應用程序的
    的瓶頸。

  • 註冊表可能是一個嚴重的安全漏洞,因爲它允許外部人員直接嚮應用程序注入代碼。

  • 無法通過構造函數傳遞依賴和硬(如我們在DI模式做)到單元測試

我使用服務定位器設計模式,我認爲是可以接受的只是對頂層您應用程序時,您的服務定位器可能不會更改