依赖注入 - 传递完整的类还是类的名称更好?
对于依赖注入,我知道我必须将一个类的实例传递给主实例,而不是主类创建它自己的实例,就像这样(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..
实际上,写出这个让我觉得这可能不是一个好的解决方案,但我仍然会发布这个,以防有人可以给我一些关于为什么我应该/不应该这样做的良好反馈。
谢谢=)
瑞安
For dependency injection, I understand that I have to pass an instance of one class to the main instance instead of the main class creating it's own instance, like so (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();
This is all fine. I know that since both Class_Two and Class_Three both implement An_Interface, they can be used interchangeably in Class_One. Class_One wouldn't know the difference between them.
My question is, is it ever a good idea to, instead of passing an instance to setOtherClass, pass a string such as "Class_Two", and have Class_One's setOtherClass method actually create the instance itself like so:
class Class_One {
...
public function setOtherClass( $other_class_name ) {
$this->_other_class = new $other_class_name();
}
...
}
Does this sort of defeat the purpose of Dependency Injection, or is this completely valid? I thought this type of set up may help me with configuration, where a user can specify which class he wants to use in a string earlier on and this can later be passed to the Class_One..
Actually, writing this out has made me think that it's probably not a good solution, but I'll still post this in case someone can give me some good feedback on why I should/shouldn't do this.
Thanks =)
Ryan
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
从理论上讲,这违背了依赖注入的目的;您正在告诉 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_Five 而 Class_One 不知道,则不能告诉 Class_One 新建 Class_Four。
That theoretically defeats the purpose of dependency injection; you are telling Class_One, which depends on An_Interface, which concrete implementation of that interface it should instantiate. That requires Class_One to know how to instantiate ANY An_Interface implementation, tightly coupling Class_One to ALL An_Interface implementations. If you add a new An_Interface Class_Four, you have to go back and tell Class_One how to instantiate a Class_Four.
In PHP, you get away with this AS LONG AS all An_Interface implementations have a parameterless constructor. However, if any implementation needs OTHER dependencies injected, you're screwed; you can't tell Class_One to just new up a Class_Four if a Class_Four needs a Class_Five that Class_One doesn't know about.
传递由接口指定的对象。否则你怎么能100%准确地知道构建这个对象需要什么?
这样,如何创建对象并不重要,您只需要知道是否可以按照您需要的方式使用它(您正在编程的接口)...
Pass an object that's specified by an interface. Otherwise how will you always know with 100% accuracy what it will take to construct the object?
That way, it doesn't matter how you create the object, you just need to know if you can use it how you need to (the interface you're programming against)...
无论哪种方式在技术上都是等效的 IMO。判断您是否正确执行依赖项注入的主要测试是查看您是否使用带有“new”或静态方法调用的任何常量字符串。您的代码看起来不错,只要在实现部分中,可以通过配置或其他机制更改类。传递类的字符串名称的唯一缺点是您无法确定它是否实现了特定接口或扩展了某些其他对象。对此的检查可能会变得混乱。但是,如果您的应用程序可以优雅地处理这个问题,那么您应该没问题。不过,传递实际实例化的对象是最好的技术。
Either way is technically equivalent IMO. The main test to tell if you are doing dependency injection right is to see if you are using any constant strings with "new" or with static method calls. Your code looks good, as long as in the implementation section, the classes can be changed via configuration or some other mechanism. The only downside with passing a string name of a class is that you can't be sure that it implements an specific interface or extends some other object. The checking for this could get messy. However, if your application can handle this issue gracefully, then you should be alright. Passing an actual instantiated object though is the best technique.