依赖注入 - 传递完整的类或类的名称是否更好?

时间:2011-02-16 18:17:38

标签: php interface dependency-injection decoupling

对于依赖注入,我理解我必须将一个类的实例传递给主实例而不是主类创建它自己的实例,就像这样(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 ..

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

谢谢=)

赖安

3 个答案:

答案 0 :(得分:5)

理论上,这违背了依赖注入的目的;你告诉Class_One,它取决于An_Interface,它应该实例化该接口的具体实现。这要求Class_One知道如何实例化ANY 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。

答案 1 :(得分:3)

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

public function __construct(MyInterface $object) {
}

这样,无论你如何创建对象,你只需要知道你是否可以根据需要使用它(你正在编程的界面)......

答案 2 :(得分:0)

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