依赖注入
依赖注入 (Dependency Injection,简称DI) Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。 采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。
而我们通常注入依赖的方式有两种:
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
控制反转是一种思想,而依赖注入是这种思想的一种实现。
下面是一段IOC容器的实现代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 <?php class Bim { public function doSomething () { echo __METHOD__ , '|' ; } } class Bar { private $bim; public function __construct (Bim $bim) { $this ->bim = $bim; } public function doSomething () { $this ->bim->doSomething(); echo __METHOD__ , '|' ; } } class Foo { private $bar; public function __construct (Bar $bar) { $this ->bar = $bar; } public function doSomething () { $this ->bar->doSomething(); echo __METHOD__ ; } } class Container { private $s = array (); public function __set ($k, $c) { $this ->s[$k] = $c; } public function __get ($k) { return $this ->build($this ->s[$k]); } public function build ($className) { if ($className instanceof Closure) { return $className($this ); } $reflector = new ReflectionClass($className); if (!$reflector->isInstantiable()) { throw new Exception ("Can't instantiate this." ); } $constructor = $reflector->getConstructor(); if (is_null($constructor)) { return new $className; } $parameters = $constructor->getParameters(); $dependencies = $this ->getDependencies($parameters); return $reflector->newInstanceArgs($dependencies); } public function getDependencies ($parameters) { $dependencies = []; foreach ($parameters as $parameter) { $dependency = $parameter->getClass(); if (is_null($dependency)) { $dependencies[] = $this ->resolveNonClass($parameter); } else { $dependencies[] = $this ->build($dependency->name); } } return $dependencies; } public function resolveNonClass ($parameter) { if ($parameter->isDefaultValueAvailable()) { return $parameter->getDefaultValue(); } throw new Exception ('I have no idea what to do here.' ); } } $c = new Container(); $c->bar = 'Bar' ; $c->foo = function ($c) { return new Foo($c->bar); }; $foo = $c->foo; $foo->doSomething(); $di = new Container(); $di->foo = 'Foo' ; $foo = $di->foo; var_dump($foo); $foo->doSomething(); ?>