依赖注入 和 依赖注入容器 是不一样的:php
你不须要一个容器来执行依赖注入,可是一个容器能够帮助你。html
PHP-DI就是这样作的:使依赖注入更加实用。git
下面是不使用DI的代码大体工做的方式:github
下面是使用DI的代码大体工做的方式:web
这是控制反转的模式,被调用者和调用者之间的依赖性控制是相反的。工具
最主要的优势是:在调用链顶部的那个老是你。你能够控制全部依赖项,并彻底控制您的应用程序的工做方式,你能够用另外一个(例如你建立的一个)来替换依赖项。this
例如,若是库X使用 Logger Y,而你想让它使用 Logger Z 呢?有了依赖注入,你就不须要更改库X的代码了。翻译
那么,使用PHP-DI的代码是如何工做的:code
简而言之,容器包含了建立和注入依赖的全部工做。htm
In short, the container takes away all the work of creating and injecting dependencies.
这是一个真实的例子,比较了一个经典的实现(使用new
或单例)和使用依赖注入。
假设你有:
class GoogleMaps { public function getCoordinatesFromAddress($address) { // calls Google Maps webservice } } class OpenStreetMap { public function getCoordinatesFromAddress($address) { // calls OpenStreetMap webservice } }
经典的作法是:
class StoreService { public function getStoreCoordinates($store) { $geolocationService = new GoogleMaps(); // or $geolocationService = GoogleMaps::getInstance() if you use singletons return $geolocationService->getCoordinatesFromAddress($store->getAddress()); } }
如今咱们想使用OpenStreetMap
而不是GoogleMaps
,咱们该怎么作?
咱们必须更改StoreService
的代码,以及全部其余使用GoogleMaps
的类。
若是没有依赖注入,你的类与它们的依赖紧耦合。
StoreService
如今使用依赖注入:
class StoreService { private $geolocationService; public function __construct(GeolocationService $geolocationService) { $this->geolocationService = $geolocationService; } public function getStoreCoordinates($store) { return $this->geolocationService->getCoordinatesFromAddress($store->getAddress()); } }
服务是使用接口 (Interface) 定义的:
interface GeolocationService { public function getCoordinatesFromAddress($address); } class GoogleMaps implements GeolocationService { ... class OpenStreetMap implements GeolocationService { ...
如今,StoreService
的用户能够决定使用哪一个实现。 它能够随时改变,没必要重写StoreService
。
StoreService
再也不与它的依赖紧耦合。
The
StoreService
is no longer tightly coupled to its dependency.
你可能会发现依赖注入会带来一个缺点:你如今必须处理注入依赖关系。
这就是容器(Container),特别是PHP-DI能够帮助你的地方。
而不是写:
$geolocationService = new GoogleMaps(); $storeService = new StoreService($geolocationService);
你能够写:
$storeService = $container->get('StoreService');
并配置哪一个GeolocationService
PHP-DI应该经过配置自动注入到StoreService
中:
$container->set('GeolocationService', \DI\create('GoogleMaps'));
若是您改变主意,如今只须要改变一行配置。
感兴趣吗? 继续阅读开始使用PHP-DI指南!
p.s. 看到PHP-DI没有中文文档,第一次对着机翻瞎翻译,若有疏漏敬请指正。