定義
依賴注入是指不是由內部生產(初始化、建構函式 __construct 中透過工廠方法、自行手動 new 的),而是由外部以引數或其他形式注入的。
解釋
簡單來說就是把依賴物件的例項化過程交給第三方(IOC容器)來實現。
控制 : 依賴物件例項化的控制。
正向 : 我們在物件中主動獲取依賴物件。
反向 : IOC容器生成依賴物件,並且把依賴物件傳遞到資源物件中。資源物件獲取依賴物件的方式反轉了,由主動建立變成被動接受了。
IOC容器 : 一個類,它負責控制所有物件的生命週期和各個物件之間的關係。
結構中包含的角色
- IocContainer (IOC容器)
- AbstractResource (抽象資源))
- Resource (具體資源)
- AbstractResourceDependent (抽象資源依賴)
- ResourceDependent (資源依賴)
最小可表達程式碼
class ResourceDependent {}
class Resource
{
private $resourceDependent;
public function __construct(ResourceDependent $resourceDependent)
{
$this->resourceDependent = $resourceDependent;
}
}
$resource = new Resource(new ResourceDependent);
簡化版Laravel服務容器程式碼
abstract class AbstractResourceDependent {}
class ResourceDependent extends AbstractResourceDependent {}
abstract class AbstractResource
{
private $resourceDependent;
public function __construct(AbstractResourceDependent $resourceDependent)
{
$this->resourceDependent = $resourceDependent;
}
public function debug()
{
return 'test';
}
}
class Resource extends AbstractResource {}
class IocContainer
{
protected $bindings = [];
protected $instances = [];
public function bind($abstract, $concrete = null)
{
if (! $concrete instanceof Closure) {
$concrete = $this->getClosure($abstract, $concrete);
}
$this->bindings[$abstract] = compact('concrete');
}
protected function getClosure($abstract, $concrete)
{
return function ($container) use ($abstract, $concrete) {
if ($abstract == $concrete) {
return $container->build($concrete);
}
return $container->make($concrete);
};
}
public function make($abstract)
{
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
$concrete = $this->getConcrete($abstract);
$object = $this->build($concrete);
return $object;
}
public function build($concrete)
{
if ($concrete instanceof Closure) {
return $concrete($this);
}
return new $concrete;
}
protected function getConcrete($abstract)
{
if (isset($this->bindings[$abstract])) {
return $this->bindings[$abstract]['concrete'];
}
return $abstract;
}
}
$app = new IocContainer;
$app->bind(AbstractResourceDependent::class, function ($app) {
return new ResourceDependent();
});
$app->bind(AbstractResource::class, function ($app) {
return new Resource($app->make(AbstractResourceDependent::class));
});
$resource = $app->make(AbstractResource::class);
var_dump($resource->debug());
實際應用場景
- Laravel的服務容器
- Spring的服務容器
本作品採用《CC 協議》,轉載必須註明作者和本文連結