簡體   English   中英

依賴注入容器和 Collections

[英]Dependency Injection Container and Collections

我一直在尋找這個主題的答案,但我無法像其他主題一樣找到令人滿意的答案,共識是穩固的。

情況

為了簡單起見:我正在將一個自定義依賴注入容器實現到我當前的一個項目中(我知道,我應該使用一個已經構建的容器,但我這樣做是出於學習目的;所以像“使用這個函數”這樣的答案容器...' 沒用),我偶然發現了一個在集合中實例化新元素的問題。

問題

想象一下,我有一個復雜的 object,例如一輛汽車。 這輛車有幾個依賴項(發動機、軸、座椅、安全氣囊……),它們同時具有它們自己的依賴項,等等。 讓 DiC(通過自動裝配或使用配置文件)構建 object 圖並使用簡單的代碼行注入所有依賴項並不是什么大問題,例如:

$car = $container->get(‘car’);

當我構建一個 CarCollection 時問題就來了,它是一個簡單的 class,它包含了一系列汽車。 當我嘗試使用一種使用數據庫中存在的所有汽車填充集合的方法時,問題就出現了。 很明顯,當我們從數據庫中調用“getAll”方法時,該集合應該能夠動態創建 Car 對象。 代碼將是這樣的:

public function populate(array $filters) {
    $all_data = $this->dao->getAll($filters); // Call the data access object to query all cars.
    foreach($all_data as $data) {
        $new_object = $this->container(‘car’); // create a template object
        $new_object->setData($data); // set the info.
        $this->items[] = $new_object; // Add to the collection.
     }
}

如果 car 不是那么復雜的 object 會更容易,因為我可以將 car fqcn 作為 carCollection 的參數傳遞並在每次迭代中使用它。 但這對於非常復雜的 object 是不可能的(或者如果我想實例化 object 的不同子類型 - 例如:貨車,皮卡,貨車...... - 取決於數據庫中的信息)。

問題。

關於收集對容器的了解:它不會破壞 DIC 哲學的目的嗎?

我猜不是一方面,因為我使用 PSR\Container 來輸入提示我傳遞給集合的容器(這會放松耦合)。 但它打破了容器根本不應該與域 model 耦合的想法。

我想到的唯一替代方法是用從作為屬性存在於集合中的原型 object 的克隆替換為每次迭代創建一個新的 object。 但是我們都知道在 php 中進行克隆會變得非常棘手並且非常難以調試(或者更糟糕的是:甚至很難知道正在發生問題)。

類似的問題。

PS:當我嘗試使用 Porxy 對象進行延遲加載時,我遇到了同樣的問題:如果我想稍后實例化完整的 object,我需要代理對象來訪問容器,這也違反了 DiC 的原則。

謝謝你們。

我認為您的問題的核心歸結為:

當我嘗試使用一種使用數據庫中存在的所有汽車填充集合的方法時,問題就出現了。

應用程序組件的object組成應獨立於任何 I/O,如 Mark Seemann 所述。 這意味着那些 object 圖的結構不能(也不應該)根據數據庫的變化而改變。

在我看來,您的Car object 是域 Object,而不是(域)服務。 因此,它更適合從服務返回Car實例的集合,而不是將集合直接注入您的應用程序組件之一。

如果我想稍后實例化完整的 object,我需要代理對象來訪問容器,這也違反了 DiC 的原則。

通常認為讓應用程序代碼依賴於 DI 容器是一種不好的做法。 這種模式稱為服務定位器反模式 Service Locator 被認為是一個壞主意的原因有很多,但重要的是要了解,當 DI 容器用於應用程序的啟動路徑(也稱為Composition Root )時,Service Locator 的缺點列表並不適用。 組合根中使用的 DI 容器不是服務定位器反模式的實現。

當您的代理類組合根中定義時,讓它們依賴於 DI 容器是完全可以的,並且您不會違反任何軟件原則或實踐。

暫無
暫無

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

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