Внедрение зависимости - лучше передать полный класс или имя класса? - PullRequest
4 голосов
/ 16 февраля 2011

Для внедрения зависимостей я понимаю, что мне нужно передать экземпляр одного класса в основной, а не основной класс, создав его собственный экземпляр, например так (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", и использовать метод setOtherClass класса Class_Oneна самом деле создайте сам экземпляр следующим образом:

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

Означает ли это побеждение цели внедрения зависимостей или это полностью допустимо?Я думал, что этот тип настройки может помочь мне с конфигурацией, где пользователь может указать, какой класс он хочет использовать в строке ранее, и это позже может быть передано в Class_One ..

На самом деле, написание этогоЭто заставило меня подумать, что это, вероятно, не очень хорошее решение, но я все равно опубликую это на тот случай, если кто-нибудь может дать мне хороший отзыв о том, почему я должен / не должен делать это.

Спасибо =)

Райан

Ответы [ 3 ]

5 голосов
/ 16 февраля 2011

Это теоретически отрицает цель внедрения зависимости;вы говорите Class_One, который зависит от An_Interface, какую конкретную реализацию этого интерфейса он должен создать.Это требует, чтобы Class_One знал, как создавать ЛЮБУЮ реализацию An_Interface, тесно связывая Class_One со ВСЕМИ реализациями An_Interface.Если вы добавляете новый An_Interface Class_Four, вы должны вернуться и сказать Class_One, как создать экземпляр Class_Four.

В PHP вам не до этого AS LONG AS, все реализации An_Interface имеют конструктор без параметров.Однако, если какая-либо реализация требует внедрения ДРУГИХ зависимостей, вы облажались;вы не можете сказать Class_One просто создать Class_Four, если Class_Four нужен Class_Five, о котором Class_One не знает.

3 голосов
/ 16 февраля 2011

Передайте объект, указанный интерфейсом.Иначе как вы всегда будете знать со 100% точностью, что потребуется для создания объекта?

public function __construct(MyInterface $object) {
}

Таким образом, не имеет значения, как вы создаете объект, вам просто нужно знать, можете лииспользуйте его так, как вам нужно (интерфейс, против которого вы программируете) ...

0 голосов
/ 16 февраля 2011

Любой способ технически эквивалентен ИМО. Основной тест, чтобы определить, правильно ли вы выполняете внедрение зависимостей, состоит в том, чтобы увидеть, используете ли вы какие-либо константные строки с «новыми» или статическими вызовами методов. Ваш код выглядит хорошо, поскольку в разделе реализации классы могут быть изменены с помощью конфигурации или другого механизма. Единственным недостатком передачи строкового имени класса является то, что вы не можете быть уверены, что он реализует определенный интерфейс или расширяет какой-то другой объект. Проверка на это может стать грязной. Однако, если ваше приложение может изящно решить эту проблему, то с вами все будет в порядке. Передача реального экземпляра объекта - лучший метод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...