2013-07-23 248 views
3

首先,對不起我的英文不好,我希望你明白我在說什麼。依賴注入和依賴不使用

這是我的問題:

讓我們假設我有一個MVC應用包括標準路由器,控制器,模型(服務)層和某種分貝連接器。
模型層依賴於數據庫連接器,控制器依賴於模型/服務,頂級「應用程序」類取決於路由器和控制器。
我的對象層次結構是這樣的:

App -> ControllerFactory -> ServiceFactory -> DAO -> DbConnection

也許,上面寫的並不像最好的應用架構不斷,但我希望把重點放在其他的事情:
當我試圖實例化一個App類,我應該將所有的依賴關係傳遞給實例化的類;類依賴關係依次具有自己的依賴關係等等。
因此,我得到所有層次堆棧立即實例化。但是如果我在某些情況下不需要訪問數據庫呢?如果某些控制器用於渲染靜態模板而沒有模型交互?
我的意思是,如果在某些特殊情況下類不需要自己的依賴關係(並且在某些情況下它可以)呢?我應該有條件地注入依賴嗎?
我真的被困在這一點,我不知道該怎麼辦。

回答

3

更新:重新仔細閱讀您的問題後,這裏是另一個建議:是的,每個類都有不同的依賴關係。

不要將每個對象注入每個其他對象。例如,一些服務可能需要DAO,所以注入它們。但是如果服務不需要DAO,請不要注入任何DAO。

我的答案的其餘部分是有效的,如果你有(例如)需要一個DAO(因此一個數據庫連接)服務不是每個方法。


你可能會找什麼是懶注射

這是注入依賴關係未加載的行爲,以便該對象僅在使用/加載時加載。

以對照術語來說,這意味着注入一個代理對象,它的外觀和行爲與原始對象(例如db連接)完全相同。

幾個DI容器(框架)支持這個,所以你不必自己創建代理。我將以PHP-DI爲例(我從事該項目的參與工作)。

下面是使用上的註釋的例子:

use DI\Annotation\Inject; 

class Example { 
    /** 
    * @Inject(lazy=true) 
    * @var My\Class 
    */ 
    protected $property; 

    /** 
    * @Inject({ "param1" = {"lazy"=true} }) 
    */ 
    public function method(My\Class $param1) { 
    } 
} 

當然,如果你不想使用註釋,你可以使用任何你想要(PHP,YAML,...)任何其他配置。這裏是相同的例如通過在純PHP配置容器:

$container->set('Example') 
    ->withProperty('property', 'My\Class', true) 
    ->withMethod('method', array('param1' => array(
      'name' => 'My\Class', 
      'lazy' => true, 
     ))); 

其他位於the documentation about Lazy Injection


注意:您可能不被使用的容器,現在(這不是一個問題),但對於解決延遲注入,這是工作了相當數量的,你可能需要開始使用一個考慮。

+0

使用代理是一個非常好的主意,我會試試看,謝謝! –

0

如果您的依賴關係構造比較複雜,只需添加一個新的工廠類,該工廠類應包含所有邏輯以爲您創建正確的對象。

class AppFactory(){ 

    __construct(all params){ 

    } 
    build(useDB=true){ 
     // logic to build 
     if(useDB){ 
      App = new App(new ControllerFactory(new ServiceFactory(new DAO(new DbConnection(params))))) 
     } else { 
      App = new App(new ControllerFactory(new ServiceFactory(null)))) 
     } 

     return App; 
    } 
}