4

对于依赖注入,我知道我必须将一个类的实例传递给主实例,而不是主类创建它自己的实例,就像这样(php):

class Class_One {
  protected $_other;
  public function setOtherClass( An_Interface $other_class ) {
    $this->_other_class = $other_class;
  }
  public function doWhateverYouHaveToDoWithTheOtherClass() {
    $this->_other_class->doYourThing();
  }
}

interface An_Interface {
  public function doYourThing();
}

class Class_Two implements An_Interface {
    public function doYourThing() { }
}

class Class_Three implements An_Interface {
    public function doYourThing() { }
}


// Implementation:
$class_one = new Class_One();
$class_two = new Class_Two();
$class_three = new Class_Three();
$class_one->setOtherClass( $class_two );
$class_one->doWhateverYouHaveToDoWithTheOtherClass();
$class_one->setOtherClass( $class_three );
$class_one->doWhateverYouHaveToDoWithTheOtherClass();

这一切都很好。我知道由于 Class_Two 和 Class_Three 都实现了 An_Interface,因此它们可以在 Class_One 中互换使用。Class_One 不会知道它们之间的区别。

我的问题是,不是将实例传递给 setOtherClass,而是传递一个诸如“Class_Two”之类的字符串,并让 Class_One 的 setOtherClass 方法像这样实际创建实例本身,这是否是一个好主意:

class Class_One {
  ...
  public function setOtherClass( $other_class_name ) {
    $this->_other_class = new $other_class_name();
  }
  ...
}

这种破坏依赖注入的目的,还是完全有效?我认为这种类型的设置可以帮助我进行配置,用户可以在前面指定他想在字符串中使用哪个类,然后可以将其传递给 Class_One..

实际上,写出来让我觉得这可能不是一个好的解决方案,但我仍然会发布这个,以防有人能给我一些关于为什么我应该/不应该这样做的好的反馈。

谢谢 =)

瑞安

4

3 回答 3

5

从理论上讲,这违背了依赖注入的目的;您正在告诉 Class_One,它取决于 An_Interface,它应该实例化该接口的哪个具体实现。这需要 Class_One 知道如何实例化任何 An_Interface 实现,将 Class_One 紧密耦合到所有 An_Interface 实现。如果你添加一个新的 An_Interface Class_Four,你必须回去告诉 Class_One 如何实例化一个 Class_Four。

在 PHP 中,只要所有 An_Interface 实现都有一个无参数的构造函数,您就可以逃脱惩罚。但是,如果任何实现需要注入其他依赖项,那你就完蛋了;如果 Class_Four 需要 Class_One 不知道的 Class_Five,您不能告诉 Class_One 只新建一个 Class_Four。

于 2011-02-16T18:23:02.920 回答
3

传递由接口指定的对象。否则,您如何始终 100% 准确地知道构建对象需要什么?

public function __construct(MyInterface $object) {
}

这样,你如何创建对象并不重要,你只需要知道你是否可以按照你的需要使用它(你正在编程的接口)......

于 2011-02-16T18:20:40.240 回答
0

无论哪种方式在技术上都是等效的 IMO。判断您是否正确进行依赖注入的主要测试是查看您是否使用任何带有“new”或静态方法调用的常量字符串。您的代码看起来不错,只要在实现部分,可以通过配置或其他一些机制更改类。传递类的字符串名称的唯一缺点是您无法确定它实现了特定接口或扩展了其他对象。对此的检查可能会变得混乱。但是,如果您的应用程序可以优雅地处理此问题,那么您应该没问题。传递一个实际的实例化对象是最好的技术。

于 2011-02-16T18:22:52.467 回答