开发者

Dependency Injection - Is it better to pass a complete class, or the name of a class?

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_cl开发者_开发百科ass ) {
    $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


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.


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?

public function __construct(MyInterface $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)...


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜