我还在学习OOP和依赖注入,还有一些我正在努力的事情。
下面是一个简单的类,它有一个通过构造函数注入的独立数据库类,并使用getAll方法返回数据库中的所有文章。我知道DI是首选,并且是最佳实践,因为它使类很容易通过单元测试进行测试并将其解耦等。
class Articles {
private $Database;
public function __construct(Database $database) {
$this->Database = $database;
}
public function getAll() {
return $this->Database->query("SELECT * FROM Articles");
}
}
但是如果我想迭代数组中的所有项并为另一个类中的每个项实例化一个新类呢? (在这种情况下,这将是一个新的任务,然后将被放入任务队列。)我可以注入队列类并重用它但我不能注入Task类,因为我正在实例化它的多个实例,所以我目前正在类中直接实例化它而不注入它是坏的。像这样:
class Articles {
private $Database;
private $Queue;
public function __construct(Database $database, Queue $queue) {
$this->Database = $database;
$this->Queue = $queue;
}
public function init() {
$tasks = [];
$articles = $this->getAll():
foreach ($articles as $article) {
$item = new Task($article);
$tasks[] = $item;
}
$queue = $this->Queue($tasks);
}
public function getAll() {
return $this->Database->query("SELECT * FROM Articles");
}
}
那么我如何实现我的愿望呢?我可以在控制器中实例化类,但这意味着故意构建逻辑以将可迭代数组暴露给控制器,当我希望它在类的init方法中完成时,所有逻辑都被组合在一起。
有什么想法吗?
答案 0 :(得分:0)
如果Task
仅用于表示数据,则它不会更改,也不需要注入数据。
无论如何,问题的解决方案是使用Builder
设计模式,注入构建器并使用它来构建对象。
// Abstract class for the builder
abstract class BaseTaskBuilder {
abstract public function build();
}
//Concrete class for builder
class GreatTaskBuilder extends BaseTaskBuilder{
public function build() {
// return a new instance of GreatTask
}
}
// Abstract class for task
abstract class BaseTask{}
// Concrete class for task
class GreatTask extends BaseTask{}
因此,您需要做的就是注入构建器,就像在代码中一样。
答案 1 :(得分:0)
我更喜欢让我的模特保持清洁。
Article
是一种数据模型,您可以使用常规CRUD
函数update()
,retrive()
,delete()
,insert
,{{1 },getAll()
等...
对于getOne($id)
来说很好,但当时Database
并不是真正的模型。
不是在模型中构建任务和队列,而是应该创建一个服务类来处理该过程并在那里使用依赖注入。
这将使单元测试变得更加容易