目标:IOC容器与反射
分析:
详解:
第一部分 IOC容器
上一节通过依赖注入,实现了对象之间的解耦;这一节我们通过IOC容器,实现对象的管理。
IOC容器,它就是一个专门用来创建对象的工厂(BeanFactory)。你要什么对象,它就给你什么对象,有了IOC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IOC容器了,通过IOC容器来建设它们之间的关系。
1、IOC容器
class B
{
public function __construct()
{
}
}
class C
{
public function __construct()
{
}
}
class D
{
public function __construct()
{
}
}
class A
{
protected $b;
protected $c;
protected $d;
public function __construct(B $b,C $c,D $d)
{
$this->b = $b;
$this->c = $c;
$this->d = $d;
}
public function getB()
{
return "B";
}
}
class IOCContainer
{
protected $instances = [];//存放对象的集合
public function __construct()
{
$this->instances['B'] = new B();
$this->instances['C'] = new C();
$this->instances['D'] = new D();
}
public function make(string $abstract)
{
return $this->instances[$abstract];
}
}
$ioc = new IOCContainer();
$b = $ioc->make('B');
$c = $ioc->make('C');
$d = $ioc->make('D');
$a = new A($b,$c,$d);
echo $a->getB();
2、反射与IOC容器
从上例中我们知道类A依赖类B,C,D;我们在IOC容器里创建了对象B,C,D,这样就可以方便的调用对象了;但是这里有2个问题
- 1、大型点的应用,无法提前生成所有的实例化对象;
- 2、没有解决多层依赖的问题,仅仅是将依赖关系从程序内部提到了外部管理;如果类B,C,D依赖类B1,C1,D1,类B1,C1,D1依赖类B2,C2,D2.....这种该怎么办?
反射+递归功能可以帮我们解决这个问题。
<?php
class B
{
protected $b1;
public function __construct(B1 $b1)
{
$this->b1 = $b1;
}
}
class C
{
public function __construct()
{
}
}
class D
{
public function __construct()
{
}
}
class B1
{
protected $b2;
public function __construct(B2 $b2)
{
$this->b2 = $b2;
}
}
class B2
{
public function __construct()
{
}
}
class A
{
protected $b;
protected $c;
protected $d;
public function __construct(B $b,C $c,D $d)
{
$this->b = $b;
$this->c = $c;
$this->d = $d;
}
public function getB()
{
return "B";
}
}
class IOCContainer
{
public static $instances = [];
public function __construct()
{
}
public function getInstances($abstract){
//获取类的反射信息,也就是类的所有信息
$reflector = new ReflectionClass($abstract);
//获取反射类的构造函数信息
$constructor = $reflector->getConstructor();
//获取反射类的构造函数的参数
$dependencies = $constructor->getParameters();
if(!$dependencies){
return self::$instances[$reflector->name] = new $abstract();
}
foreach ($dependencies as $dependency) {
if(!is_null($dependency->getClass())){
$p[] = $this->make($dependency->getClass()->name);//递归
}
}
//创建一个类的新实例,给出的参数将传递到类的构造函数
return self::$instances[$reflector->name] = $reflector->newInstanceArgs($p);
}
public function make($abstract)
{
return $this->getInstances($abstract);
}
}
$ioc = new IOCContainer();
$a = $ioc->make('A');
echo "<pre>";
var_dump(IOCContainer::$instances);
echo $a->getB();