2010-02-13 37 views
3

它是如何完成的?當您無法控制實例化和用法時依賴注入

我有一個Model類是許多子類的父類,並且該模型依賴於數據庫連接和緩存機制。

現在,它開始變得麻煩:我無法控制每個對象如何被實例化或使用,但是我控制了子類使用的方法。

目前我已轉向使用靜態方法和依賴注入的性質,因此:

 
class Model 
{ 
    private static $database_adapter; 
    private static $cache_adapter; 
    public static function setDatabaseAdapter(IDatabaseAdapter $databaseAdapter) 
    { 
     self::$databaseAdapter = $databaseAdapter; 
    } 
    public static function setCacheAdapter(ICacheAdapter $cacheAdapter) 
    { 
     self::$cacheAdapter = $cacheAdapter; 
    } 
} 

而一直都很順利,但感覺髒(它所有型號創建一個全局狀態)。我已經考慮了工廠模式,但是從子類中去除了對實例化的控制(我如何在它的構造函數中實例化一個具有可變數量參數的對象?)。

現在我不知所措。任何幫助,將不勝感激。

回答

1

據我所知,這是一個完全可以接受的選擇。由PHPUnit的創建者Sebastian Bergmann提出的另一種可能性是具有$測試靜態屬性。你可以閱讀他最近關於Testing of Singletons的文章。這聽起來像你有類似的問題。

0

對於設置默認適配器,您的解決方案將會很好,但我會爲單個模型添加一種方法來使其具有不同的適配器。試想一下:

abstract class Model { 
    protected $_database_adapter; 
    protected $_default_database_adapter; 

    public function getDatabaseAdapter() { 
     if(!$this->_database_adapter) { 
      if(self::$_default_database_adapter) { 
       $this->_database_adapter = self::$_default_database_adapter; 
      } else { 
       throw new Exception("No adapter set yet"); 
      } 
     } 
     return $this->_database_adapter; 
    } 

    public function setDatabaseAdapter(IDatabaseAdapter $databaseAdapter) { 
     $this->_database_adapter = $databaseAdapter; 
    } 

    public static function setDefaultDatabaseAdapter(IDatabaseAdapter $databaseAdapter) { 
     self::$_default_database_adapter = $databaseAdapter; 
    } 
} 

當然,你可以提取所有靜態方法/屬性爲RegistryContainer或其他任何中央。

例如,您可能不想從整個應用程序的同一數據庫主機收集數據。然後你原來的腳本將如下所示:

Model::setDatabaseAdapter($default); 
$my_model->query('....'); 
Model::setDatabaseAdapter($another_adapter); 
$my_other_model->query('....'); 
Model::setDatabaseAdapter($default); 

這是非常相似:

mysql_select_db('default_db'); 
mysql_query('...'); 
mysql_select_db('other_db'); 
mysql_query('...'); 
mysql_select_db('default_db');