在理解依赖注入方面遇到了问题
在理解依赖注入方面遇到了问题
我正在进行一个小项目,试图尽可能多地掌握基础知识,对我来说,这意味着不使用预制框架(正如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的成员变量间接获取其数据库连接),但如果需要调用一个需要另一个类的类,而这个类又需要另一个类,那么情况可能会变得很复杂。不过,我认为这可能只是代码异味。
我对此是否正确理解依赖注入?欢迎任何批评和建议。