2010-02-13 49 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');