2015-09-07 64 views
2

給定的類:Php,爲什麼「全球容器」不好,以及如何避免它?

class Container 
{ 
    public function getServiceX() 
    { 
     create and return it 
    } 

    public function setServiceX ($obj) 
    { 
    } 
} 

此存儲的對象的實例。你可以把它當作一個工廠。在行動:

public function addTitle() 
{ 
    Container::getServiceX()->doIt(); 
} 

他們說它的壞,因爲它的「全球」。但物體可以改變,所以它可以滿足DI - 但傷害LoD。 如果那不好,有什麼好的解決方案?如何確保一個班級到達serviceX?

+3

全局通常被視爲壞,因爲人們不知道如何正確地對待他們。但是,對於某些使用情況,將類用作單例實例可能完全有效。我的問題是更多......他們是誰? – Tschallacka

回答

3

本質上這是一個服務定位器或服務工廠。你甚至可以稱之爲依賴注入容器。這本身就非常好。事實上它很棒。問題在於你靜態調用它!有

class Foo { 

    protected $container; 

    public function __construct(Container $container) { 
     $this->container = $container; 
    } 

    public function addTitle() { 
     $this->container->getServiceX()->doIt(); 
    } 

} 

,現在你完全依賴注入和去耦:你應該注入你的依賴注入容器到類。

通過靜態耦合調用,您仍然可以進入首次嘗試避免使用依賴注入容器的情況。如果你需要注入一個帶有服務X的類和另一個帶有稍微不同配置的服務X實例的類,但是你正在靜態調用同一個只能容納一個服務X的容器?您正在通過將靜態調用與您的容器分離並允許注入不同配置的容器來解決此問題。

+1

@John您可能對此感興趣:[如何不使用靜態技術來殺死您的測試性](http://kunststube.net/static/) – deceze

+0

當然,但爲什麼甚至要實例化這個Container?不需要它的一個實例。 –

+2

因爲這正是OOP的全部內容。因爲可能*今天*你不能同時看到'容器'有兩個不同的實例*。但是明天你可能會發現自己處於我在答案中描述的狀態,並希望你可以有兩個獨立的容器實例。 – deceze

1

使用全局包含器會使測試代碼變得更加困難。你也沒有太多的對象狀態控制。它違背了SOLID。

依賴注入是一種更好的方法。

檢查此鏈接What's the difference between the Dependency Injection and Service Locator patterns?

在使用依賴注入,你可以很容易地樣機的對象,使他們易於測試。您不會靜態地傳遞或創建它們,但您可以通過服務的構造函數傳遞它們。

您還可以檢查Symfony2的開發者是如何做的:http://symfony.com/doc/current/components/dependency_injection/index.html

+0

,但您也可以爲Container設置對象,而不僅僅是對它們進行硬編碼。 –

相關問題