Пожалуйста, простите за возможную наивность этого вопроса, однако я действительно запутался. Похоже, что хорошей практикой является использование внедрения зависимостей для разделения вашего кода, чтобы ваши классы были загружены своими зависимостями. ПОЖАЛУЙСТА, представьте следующее, где класс Foo зависит от класса Bar
namespace Classes;
class Foo{
protected barInstance;
public function __construct(Bar $barInstance){
$this->barInstance=$barInstance;
}
}
Однако, если вы автоматически загружаете свои классы, то, безусловно, следующее делает то же самое без необходимости использования DI?
namespace Classes;
use Classes/Bar;
class Foo{
protected barInstance;
public function __construct(){
$this->barInstance=new Bar;
}
}
Спасибо всем ответчикам.
Автозагрузка гарантирует, что ваш класс определен, когда вы ссылаетесь на него. Внедрение зависимостей дает вам гибкость в отношении того, какой экземпляр объекта вы используете.
В вашем примере, скажем, ваш Bar
Класс управляет подключением к базе данных. И скажем, иногда вы хотите подключиться к другой базе данных.
public function __construct(){
$this->barInstance = new Bar();
}
Теперь вы должны рефакторинг вашего Foo
класс для обработки изменения, потому что вы тесно связали его с экземпляром Bar
,
public function __construct(Bar $barInstance){
$this->barInstance = $barInstance;
}
Теперь без изменений Foo
Я могу создать другой экземпляр Bar
для разных ситуаций. Обычно полезным примером этого являются юнит-тесты.
В обоих случаях автозагрузка убедилась, что Bar
и все его собственные зависимости определены вне Foo
,
Возьмите пример с подключением к базе данных.
у тебя есть
public class foo {
public function __construct(DbConnectionInterface $db) { ... }
}
public class foo2 {
public function __construct(DbConnectionInterface $db) { ... }
}
...
и так далее
В вашем «сервисном контейнере» у вас есть что-то подобное
$db = new PdoDbConnection(); // which implements DbConnectionInterface
$service['foo'] = new foo($db);
$service['foo2'] = new foo2($db);
Если завтра вы захотите использовать что-то еще, кроме pdo, тогда вам просто нужно создать новое соединение, реализующее интерфейс, а затем вы можете изменить свое соединение с БД в одном месте.
$db = new NotPdoDbConnection(); // which implements DbConnectionInterface
$service['foo'] = new foo($db);
$service['foo2'] = new foo2($db);
Если вы не использовали DI, то вы должны были изменить новый PdoConnection () на новый NotPdoConnection () во всех классах, использующих этот класс. Но в этом случае автозагрузка не может вам помочь. Как сказал его ответ, его два разных понятия.
это «пустышка», но вы можете прочитать несколько интересных статей о DI
http://fabien.potencier.org/what-is-dependency-injection.html
http://www.martinfowler.com/articles/injection.html
Это две разные концепции. Автозагрузка позволит вам не включать файлы в ваши сценарии и позволит вам разделить ваши классы по концепции. Что касается внедрения зависимостей, если у Bar есть дополнительные зависимости и его нельзя просто создать с помощью new Bar (), а вместо этого нового Bar ($ dep1, $ dep2), то ваша логика для создания Bar будет похоронена внутри конструктора Foo, как а также конструктор любого другого класса, который требует Bar. Инвертируя создание бара зависимости в другом месте, прежде чем вводить ее, вы освобождаете Foo от этой дополнительной ответственности.
Автозагрузка и внедрение зависимостей — это не связанные понятия.
Автозагрузчик знает, как загрузить классы. Когда простое утверждение типа new Foo()
работает, переводчик должен знать определение Foo
учебный класс. Если он еще не знает об этом, он вызывает автозагрузчик, пока класс не станет доступным. Автозагрузчики знают, где каждый класс определен, и включают правильный файл.
Контейнер внедрения зависимостей знает, как создавать объекты различных типов. Он не знает (и не заботится) о загрузке классов. Предполагается, что при запуске new Bar()
класс Bar
уже определено (или может быть загружено автоматически).