依赖注入
    从应用程序的角度来讲,把依赖注入,应用程序依赖容器创建并注入它所需要的外部资源,
控制反转
从容器的角度来描述,容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源
依赖注入与控制反转,其实是一个东西,描述角度不同而已,是一种设计模式
反射
通过类,获取知道他所依赖的类
容器
盛放对象的容器,通过容器调用类,会将类所需要的依赖都注入好,返回最终实例
三个类  A类依赖B类 B类依赖C类,互相继承或者引入的关系,耦合读很高,
使用依赖注入后,实例化调用 new A(new B(new C())) 定义层级关系了
使用容器,是直接用容器处理这些,有的容器需要自己手动处理这些关系,有的利用反射,自己实现,例子比较简单,PHP框架都使用了容器
<?phpclass Bread{}class Bacon{}class Hamburger{protected $materials;public function __construct(Bread $bread, Bacon $bacon){$this->materials = [$bread, $bacon];echo 1;}}class Cola{}class Meal{protected $food;protected $drink;public function __construct(Hamburger $hamburger, Cola $cola){$this->food = $hamburger;$this->drink = $cola;echo 1;}}//容器类class Container{/*** 获取类实例** @param string $class* @param array $params* @return object*/public function make(string $class, array $params = []){if (isset($this->binds[$class])) {return ($this->binds[$class])->call($this, $this, ...$params);}return $this->resolve($class);}/*** 通过反射获取对象** @param $abstract* @return object* @throws ReflectionException*/protected function resolve($abstract){// 获取反射对象$constructor = (new ReflectionClass($abstract))->getConstructor();// 构造函数未定义,直接实例化对象if (is_null($constructor)) {return new $abstract;}// 获取构造函数参数$parameters = $constructor->getParameters();$arguments = [];foreach ($parameters as $parameter) {// 获得参数的类型提示类$paramClassName = $parameter->getClass()->name;// 参数没有类型提示类,抛出异常if (is_null($paramClassName)) {throw new Exception('Fail to get instance by reflection');}// 实例化参数$arguments[] = $this->make($paramClassName);}return new $abstract(...$arguments);}}$ewew = new Container();//返回的就是最终的对象$ewew->make(Hamburger::class);
