2012-03-08 68 views
3

這裏有很多關於這方面的討論,但似乎沒有人真正回答這個問題。DI容器對工廠有什麼好處?

我目前正在考慮使用Symfony 2 service container。我越是看着它,看起來就越能像服務工廠那樣做同樣的事情。請看下面的例子:

services.yml

services: 
    my_mailer: 
     class:  Acme\Mailer 
     arguments: [sendmail] 
    newsletter_manager: 
     class:  Acme\Newsletter\NewsletterManager 
     arguments: [@my_mailer] 

現在得到的通訊經理,我做這樣的事情:

// this has been configured with the above yml file 
$serviceContainer = new ServiceContainer(); 
$newsletterManager = $serviceContainer->get("newsletter_manager"); 

然而,考慮下面的工廠樣式代碼:

class ServiceContainer 
{ 
    public function getMyMailer() 
    { 
     return new Acme\Mailer("sendmail"); 
    } 

    public function getNewsletterManager() 
    { 
     return new Acme\Newsletter\NewsletterManager($this->getMyMailer()); 
    } 
} 

然後使用它:

$serviceContainer = new ServiceContainer(); 
$newsletterManager = $serviceContainer->getNewsletterManager(); 

有什麼我在這裏失蹤?因爲如果工廠可以爲我完成所有這些工作,我不會真正看到使用DI容器的好處。

我聽說使用工廠會導致您的代碼「依賴工廠」。我要麼不理解這個論點,要麼與工廠辯論的人混淆起來。只有頂層類(組合根)纔會有對工廠的引用,就像它是唯一一個引用DI容器一樣。

回答

2

有什麼我在這裏失蹤?因爲如果工廠可以爲我做所有這些工作,我真的不會看到使用DI容器的好處。

是的 - 您正在使用DI容器使用Service Locator (anti-)pattern而不是將您的依賴關係注入到您的類中。你的班級不應該引用你的DI容器。

相反,應該只有一個聚合根目錄,您可以在其中創建容器並解決所有依賴關係。一旦解決了頂級類實例的問題,就可以使用Hollywood Principle使用IoC容器解析其所有依賴關係(以及依賴關係等依賴關係) - 當創建類實例時,所有的依賴關係都被傳入,實例從不要求自己的依賴。

+0

你能詳細解釋一下嗎?這些例子在功能上是相同的。只有組合根有一個對工廠的引用,這是與DI容器相同的地方。在這兩個例子中都沒有負責完成自己的依賴關係的類。 – ryeguy 2012-03-08 22:02:43

+0

如何使用工廠傳遞依賴項的依賴關係?換句話說,使用IoC容器,您可以解析完整的依賴關係圖 – BrokenGlass 2012-03-08 22:04:54

+0

「NewsletterManager」具有「MyMailer」的依賴關係。當您在工廠調用getNewsletterManager()時,它會調用工廠上也是*的getMyMailer()。這是我的理解,服務定位器模式將是我有'電子郵件管理器'解決它的依賴關係本身,在構造函數或什麼的地方。 – ryeguy 2012-03-08 22:07:05