阅读这篇关于依赖注入的伟大文章之后:http://miller.limethinking.co.uk/2011/07/07/dependency-injection-moving-from-basics-to-container/
我意识到我的小框架在很大程度上已经使用了Denedency Injection Container。
我有一个App类,管理创建所有服务Database,Config,Session,并且能够实现不同的类。
但我意识到一个部分导致问题我将一个Event调度程序传递给我的框架中的很多基类,但是每个类都使用调度程序,如:
$this->dispatcher->fire(new FB_Event('FB.Database.Model.beforeUpdate', $this, array('pk' => $pk, 'row' => $row)));
所以当你看到我在那里使用一个新的,所以我无法完全单元测试我的课程。我不想将我的App容器传递给所有应用程序,因为它是调试后的噩梦,因为App包含数据库,会话和其他类不需要的大量服务的实例。
解决这个问题的最佳方法是什么,因为我无法通过依赖注入传递FB_Event,因为相同的函数通常会触发2个事件:
public function delete($pk) {
$e = $this->dispatcher->fire(new FB_Event('FB.Database.Model.beforeDelete', $this, array('pk' => $pk)));
$pk = $e->params['pk'];
if ($e->preventDefault()) {
return false;
}
$this->requirePK();
list ( $where, $params ) = $this->pkParts(null, $pk);
$sql ="DELETE FROM {$this->name} WHERE $where";
$stm = $this->db->execute($sql, $params);
$this->dispatcher->fire(new FB_Event('FB.Database.Model.afterDelete', $this, array('pk' => $pk)));
return!(bool) $stm->errorCode();
}
我的一个解决方案是向调度程序添加一个名为fireEvent的新函数,它将负责创建新的FB_Event,它将删除所有耦合。但是会在调度程序和事件之间添加耦合,这样会更糟糕。
public function fireEvent($name, $target, $params = array()) {
return $this->fire(new FB_Event($name, $target, $params = array()));
}
你会在容器中创建一些EventFactory并将其传递给Dispatcher吗?
这是否过度去除依赖于像Event这样的小对象?
谢谢你的建议
我实际上认为你建议的解决方案是最好的答案。 你应该避免在代码中实例化FB_Event,因为它很难(-er)测试和耦合你的代码。 在您的fireEvent方法中,是的,Dispatcher类和Event类之间存在耦合,但Dispatcher应该知道事件,因为它就是它的调度。 是的,要避免耦合,但有些课程有时需要了解其他课程; 不能总是避免耦合。 fireEvent方法的好处在于它是一个接缝,因此可以用来在将来破坏代码。
为什么下来投票?
我终于重申了Event是一个虚拟的小对象,fireEvent方法是从FB_Event中解耦所有基类的最佳方法。
What is the best way of resolving this since I cannot pass an FB_Event
through dependency injection, since the same function usually fire 2
event:
您可以通过在FB_Event类中使用setter来解决此问题。 例如,将FB_Event(DI)的实例传递给相关类,然后将其用作:
public function delete($pk) {
$this->fb_event->setName('FB.Database.Model.beforeDelete');
$this->fb_event->setTarget($this);
$this->fb_event->setParams(array('pk' => $pk));
$e = $this->dispatcher->fire($this->fb_event);
$pk = $e->params['pk'];
if ($e->preventDefault()) {
return false;
}
$this->requirePK();
list ( $where, $params ) = $this->pkParts(null, $pk);
$sql ="DELETE FROM {$this->name} WHERE $where";
$stm = $this->db->execute($sql, $params);
$this->fb_event->reset();
$this->fb_event->setName('FB.Database.Model.afterDelete');
$this->fb_event->setTarget($this);
$this->fb_event->setParams(array('pk' => $pk));
$this->dispatcher->fire($this->fb_event);
return!(bool) $stm->errorCode();
}
这个方法可以工作,但我更喜欢使用不同的实例,因为dispatch方法返回带有修改的params的Event对象。