在理解依赖注入方面遇到了问题

4 浏览
0 Comments

在理解依赖注入方面遇到了问题

我正在进行一个小项目,试图尽可能多地掌握基础知识,对我来说,这意味着不使用预制框架(正如Jeff曾经说过的,“不要重新发明轮子,除非你计划学习更多关于轮子的知识”[重点在于学习])并遵循测试驱动开发原则。

在我的探索过程中,我最近遇到了依赖注入的概念,这似乎是测试驱动开发的基本要素。但我对此还不太理解。到目前为止,我了解的是,它大致意味着“让调用者传递给类/方法它可能需要的其他类,而不是让它们自己创建这些类”。

我有两个例子需要使用依赖注入来解决。对于这些重构,我是否走在正确的道路上?

数据库连接

我计划使用单例模式来处理数据库,因为我目前不打算使用多个数据库。最初,我的模型看起来应该像这样:

class Post {  
  private $id;  
  private $body;  
  public static function getPostById($id) {  
    $db = Database::getDB();  
    $db->query("SELECT...");  
    //等等  
    return new Post($id, $body);
  }  
  public function edit($newBody) {  
    $db = Database::getDB();  
    $db->query("UPDATE...");  
    //等等  
  }  
}  

使用依赖注入,我认为它应该像这样:

class Post {  
  private $db; // 新成员
  private $id;  
  private $body;  
  public static function getPostById($id, $db) { // 新参数   
    $db->query("SELECT...");  // 使用参数
    //等等  
    return new Post($db, $id, $body);
  }  
  public function edit($id, $newBody) {   
    $this->db->query("UPDATE...");  // 使用成员
    //等等  
  }  
} 

我仍然可以使用单例模式,在应用程序设置中指定凭证,但我只需从控制器传递它(控制器本身无法进行单元测试):

Post::getPostById(123, Database::getDB);

模型调用模型

以帖子的浏览次数为例。由于判断一个浏览是否是新浏览的逻辑不特定于Post对象,它只是一个独立对象上的静态方法。然后,Post对象将调用它:

class Post {
  //...
  public function addView() {
    if (PageView::registerView("post", $this->id) {
     $db = Database::getDB();
     $db->query("UPDATE..");
     $this->viewCount++;
   }
}

使用依赖注入,我认为它应该像这样:

class Post {
  private $db;
  //...
  public function addView($viewRegistry) {
    if ($viewRegistry->registerView("post", $this->id, $this->db) {
     $this->db->query("UPDATE..");
     $this->viewCount++;
   }
}

这将使控制器的调用变为:

$post->addView(new PageView());

这意味着实例化一个只有静态方法的类的新实例,这对我来说不太好(我认为在某些语言中是不可能的,但在这里可以实现,因为PHP不允许类本身是静态的)。

在这种情况下,我们只进行了一层调用,所以由控制器实例化一切似乎是可行的(尽管PageView类通过Post的成员变量间接获取其数据库连接),但如果需要调用一个需要另一个类的类,而这个类又需要另一个类,那么情况可能会变得很复杂。不过,我认为这可能只是代码异味。

我对此是否正确理解依赖注入?欢迎任何批评和建议。

0