php的依赖注入和控制反转

一、初步探索

  1. 控制反转,反转是相对于正转来说的,下面是正转的代码
class A{
  public function __construct(){
    $this->b = new B();
  }
  public function aMethod(){
    return $this->b->bMethod();
  }
}
class B{
  public function __construct(){}
  public function bMethod(){
    return 12;
  }
}

$b = (new A)->aMethod();

A类中的代码需要依赖B类,然后我们就在A的代码中实例化B类,然后调用B类中的方法
缺点:如果有多个地方需要用到B的实例化对象的话,就需要复制多次该代码

  1. 控制反转的代码
class A{
  protected $b;
  public function __construct(B $b){
    $this->b = $b;
  }
  public function getB(){
    return $this->b->abc();
  }
}
class B{
  public function __construct(){}
  public function abc(){
    echo 23;
  }
}
class Ioc{
  protected $instance = [];
  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];
  }
}
echo '
'
$ioc = new Ioc();
$b = $ioc->make('B');
$a = new A($b);
$a->getB();

控制反转在外部处理好依赖关系,不需要在A中直接new B,而是让IoC容器将B给我,这就叫控制反转IoC
书面解释:将组件间的依赖关系从程序内部提到外部来管理。控制反转是站在A的立场来看的,它是拿B的

控制反转是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是自己把控的,而现在这种权利转移到第三方,比如转移交给了IoC容器,它是一个专门用来创建对象的工厂(BeanFactory),你要什么对象他就给你什么对象,有了IoC容器,依赖关系就变了,原先的依赖关系就没了,他们都依赖IoC容器里,通过ioc容器来建立他们之间关系
书面解释:组件间的依赖通过外部以参数或其他形式注入就是依赖注入DI,依赖注入是站在IoC立场上来看的,它是送B的

依赖 注入:IoC/DI容器注入某个对象所需要的外部资源
控制 反转:IoC/DI容器控制对象、控制对象实例的创建,主动权的转移

缺点明显:
1、无法提前生成所有的实例化对象
2、没有解决多层依赖的问题,仅仅是将依赖关系从程序内部提到了外部管理

二、进一步探索

在PHP运行时,扩展分析程序,导出或提出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取信息以及动态调用方法的功能称为反射API

class A{

  public function __construct(B $b){
    $this->b = $b;
  }

   public function getB(){
    $this->b->bMethod();
  }
}
class B{
  public function __construct(C $c, D $d){
    $this->c = $c;
    $this->d = $d;
  }

  public function bMethod(){
    echo '我是B中的方法bMethod()';
  }
}
class C{
  public function __construct(){}
  public function cMethod(){
    echo '我是C中的方法cMethod()';
  }
}
class D{
  public function __construct(){}
  public function dMethod(){
    echo '我是B中的方法dMethod()';
  }
}

class Ioc{
  protected $instance = [];
  public function __construct(){}
  public function getInstance($abstract){
    //获取类的反射信息,也就是类的所有信息
    $reflector = new ReflectionClass($abstract);
    //echo $reflector->getDocComment();//获取类的注释信息
    //获取反射类的构造函数信息
    $constructor = $reflector->getConstructor();
    //获取反射类的构造函数的参数
    $dependencies = $constructor->getParameters();
    if(!$dependencies){
      return new $abstract();
    }
    //一个类可能有多个依赖类
    foreach ($dependencies as $dependency){
      if(!is_null($dependency->getClass())){
        $p[] = $this->make($dependency->getClass()->name);
        //这里$p[0]是c的实例化对象,$p[1]是D的实例化对象
      }  
    }
    //创建一个类的新实例,给出的参数将传递到类的构造函数
    //构造出B的实例化对象,向上反推到A的实例化对象
    return $reflector->newInstanceArgs($p);
  }
  public function make($abstract){
    return $this->getInstance($abstract);
  }
}
$ioc = new Ioc();
$a = $ioc->make('A');
$a->getB();

你可能感兴趣的:(php的依赖注入和控制反转)