依赖注入
    从应用程序的角度来讲,把依赖注入,应用程序依赖容器创建并注入它所需要的外部资源,
    控制反转
    从容器的角度来描述,容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源
    依赖注入与控制反转,其实是一个东西,描述角度不同而已,是一种设计模式
    反射
    通过类,获取知道他所依赖的类
    容器
    盛放对象的容器,通过容器调用类,会将类所需要的依赖都注入好,返回最终实例

    三个类 A类依赖B类 B类依赖C类,互相继承或者引入的关系,耦合读很高,
    使用依赖注入后,实例化调用 new A(new B(new C())) 定义层级关系了
    使用容器,是直接用容器处理这些,有的容器需要自己手动处理这些关系,有的利用反射,自己实现,例子比较简单,PHP框架都使用了容器

    1. <?php
    2. class Bread
    3. {
    4. }
    5. class Bacon
    6. {
    7. }
    8. class Hamburger
    9. {
    10. protected $materials;
    11. public function __construct(Bread $bread, Bacon $bacon)
    12. {
    13. $this->materials = [$bread, $bacon];
    14. echo 1;
    15. }
    16. }
    17. class Cola
    18. {
    19. }
    20. class Meal
    21. {
    22. protected $food;
    23. protected $drink;
    24. public function __construct(Hamburger $hamburger, Cola $cola)
    25. {
    26. $this->food = $hamburger;
    27. $this->drink = $cola;
    28. echo 1;
    29. }
    30. }
    31. //容器类
    32. class Container
    33. {
    34. /**
    35. * 获取类实例
    36. *
    37. * @param string $class
    38. * @param array $params
    39. * @return object
    40. */
    41. public function make(string $class, array $params = [])
    42. {
    43. if (isset($this->binds[$class])) {
    44. return ($this->binds[$class])->call($this, $this, ...$params);
    45. }
    46. return $this->resolve($class);
    47. }
    48. /**
    49. * 通过反射获取对象
    50. *
    51. * @param $abstract
    52. * @return object
    53. * @throws ReflectionException
    54. */
    55. protected function resolve($abstract)
    56. {
    57. // 获取反射对象
    58. $constructor = (new ReflectionClass($abstract))->getConstructor();
    59. // 构造函数未定义,直接实例化对象
    60. if (is_null($constructor)) {
    61. return new $abstract;
    62. }
    63. // 获取构造函数参数
    64. $parameters = $constructor->getParameters();
    65. $arguments = [];
    66. foreach ($parameters as $parameter) {
    67. // 获得参数的类型提示类
    68. $paramClassName = $parameter->getClass()->name;
    69. // 参数没有类型提示类,抛出异常
    70. if (is_null($paramClassName)) {
    71. throw new Exception('Fail to get instance by reflection');
    72. }
    73. // 实例化参数
    74. $arguments[] = $this->make($paramClassName);
    75. }
    76. return new $abstract(...$arguments);
    77. }
    78. }
    79. $ewew = new Container();
    80. //返回的就是最终的对象
    81. $ewew->make(Hamburger::class);