簡體   English   中英

服務定位器與依賴注入

[英]Service Locator vs. Dependency Injection

我正在用很多這樣的語句審查代碼:

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

我希望像

private SomeInterface x;

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

第一種方法有問題嗎? 好的,依賴關系不是那么明顯,但是可以通過 Locator 的配置輕松地交換實現。

Martin Fowler 寫了一篇關於 DI vs Locators的文章:

對於 DI:

  • 更容易確定組件具有哪些依賴項 - 查看構造函數。
  • 組件不依賴於 Service Locator,因此如果該組件與不同的框架一起使用,則不會出現問題。
  • DI 可能使測試更容易,但良好的服務定位器機制將使存根同樣可行

反對 DI:

  • 更難調試和理解。
  • 組件一旦配置就不能從注入器請求額外的服務。

我個人認為第一個基於定位器的方法本質上沒有什么不好的——我猜 DI 確實對此進行了標准化,所以如果它可用,我會使用它。 所有好的想法都傾向於在某個時候最終成為框架,所以這就是這里發生的事情。 再加上 DI,您可以利用其他注釋、范圍等,而無需編寫自己的代碼。 您的項目使用的定制代碼越少,IMO 就越好。 不過,我會把最后一句話留給福勒:

服務定位器和依賴注入之間的選擇不如在應用程序中將服務配置與服務使用分離的原則重要。

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

對於第二種用法,我喜歡構造函數注入,它的順利執行非常好。 但我不想使用屬性(Java 中的注釋?)因為任何時候我可能想要更改我正在使用的 DI 容器並且我不想從所有類中刪除屬性。

服務定位器模式使用稱為“服務定位器”的中央注冊表,它根據請求返回執行特定任務所需的信息。

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

  • 對於系統的 rest,放置在注冊表中的內容實際上是黑匣子。 這使得檢測和從錯誤中恢復變得更加困難,並且可能使整個系統的可靠性降低。

  • 注冊表必須是唯一的,這可能使其成為
    並發應用程序。

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

  • 無法通過構造函數傳遞依賴項(就像我們在 DI 模式中所做的那樣)並且難以進行單元測試

而且我認為只有在您的服務定位器可能不會改變時,才可以在應用程序的頂層使用服務定位器設計模式

服務定位器模式並沒有什么“錯誤”,

在這種特殊情況下,支持 DI 的一個主要論點是可測試性。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM