2012-08-13 185 views
1

我一直在練習我的整個PHP應用程序的構造函數依賴注入。我不想用對象創建來拋棄我的代碼,所以工廠來拯救,或者至少我想。依賴注入與工廠

我開始與工廠連接最多的部件,然後一些工廠開始使用其他工廠拿到的依賴,極大的,使所有的創建代碼在一個地方。然而,一旦工廠開始相互使用(或者如下面的代碼本身),我遇到了循環依賴問題,這些問題根本無法解決。例如,我的MapperFactory利用自身注入與其他地圖製圖員(他們需要彼此建立起一個完整的對象圖「預先加載」):

class MapperFactory 
{ 
    public function create($type) 
    { 
     switch (true) { 
      case 'Item': 
       $mapper = new ItemMapper(
        $this->create('Field') 
       );    
       break; 
      case 'Field': 
       $mapper = new ItemMapper(
        $this->create('Item') 
       ); 
       break; 
      default: 
       throw new Exception('Unknown mapper'); 
     } 
     return $mapper; 
    } 

} 

$mf = new MapperFactory(); 
$mf->create('Item'); 

它是一個簡單的例子,但一個越來越普遍的問題,因爲該應用程序正在發展。錯誤從PHP(Xdebug的安裝)背面是:

Fatal error: Maximum function nesting level of '100' reached, aborting! 

完全理解爲什麼PHP是抱怨(雖然沒有看到它的到來TBH)。

我的問題是,我已徹底無緣工廠的地步?我正確使用工廠嗎?它看起來不是,但除了循環依賴(非常重要但是),工廠是將所有構建/佈線邏輯遠離主應用程序的優雅解決方案。

+0

我不認爲它與工廠的問題。首先,我沒有得到「開關(真)」部分。不應該是「切換($類型)」?其次,你的代碼(如果我閱讀正確的話)無止境地遞歸。也許你應該只在你準備好使用那個實例變量時創建子字段或子項目。或者想出一些結束遞歸的東西。 – Marvo 2012-08-13 17:25:17

+0

我猜'開關(真)......不是你想寫的東西。但即使使用'switch($ type)',如果'$ type'是'Field'或'Item',你會得到一個無限循環。 – Yoshi 2012-08-13 17:26:14

回答

1

你可以嘗試使用二傳手注射的依賴關係。然後你會創建這樣的映射器:

$itemMapper = new Mapper(); 
$fieldMapper = new Mapper(); 
$itemMapper->setRelatedMapper($fieldMapper); 
$fieldMapper->setRelatedMapper($itemMapper); 

然後使用開關只是返回映射器。這應該在創建對象時擺脫循環依賴關係。如果你這樣做是作爲一種OR/M的東西來連接數據庫,你也許應該看看Doctrine2或Propel這樣的東西,只是爲了節省你在那裏發明輪子的麻煩已經嘗試過並經過測試。

+0

是的,我已經嘗試過setter,儘管考慮依賴是一個'需求',因此使它們在構造函數中是必需的。但絕對是我不得不再看的東西。 ORM方面,我需要通過SOAP和REST服務持久化對象,因此需要保持靈活性。 – user1595982 2012-08-13 20:04:07

+0

呀,構造函數是強制執行的關係的方式,但在你的榜樣它創建了一個循環,因爲「項目」創造「領域」,它創造了「項目」等等......通過使用制定者,你只是分享對象之間的引用,以及一個var轉儲或類似的東西也會顯示一個無盡的對象層次結構,至少它不會中斷。你只創建兩個實例,而不是無窮大...... – Pinetree 2012-08-13 22:18:11

0

看起來MapperFactorycreate方法導致無限循環。

switch(true) { 
    case 'Item' : // this will always be selected http://php.net/manual/en/language.types.type-juggling.php 
    $mapper = new ItemMapper(
     $this->create('Field'); // Forces loop, 
    ); 

如果交換機正在尋找TRUE匹配,則情況下的工作必須是一個布爾

switch(true) { 
    case $type == 'Item' : 
    // ... 
    break; 
    case $type == 'Field' : 
    // ... 
} 
+0

是的,對不起,考慮到問題的背景(循環依賴),這是不可原諒的。它應該是開關($ type)。 – user1595982 2012-08-13 19:57:40