php設計模式-簡單依賴注入容器+自動繫結特性
阿新 • • 發佈:2020-07-23
class C { public function sayHello() { echo 'I am C'; } } class B { private $_c; public function __construct(C $c) { $this->_c = $c; } public function sayHello() { echo 'I am B'; $this->_c->sayHello(); } } class A { private $_b; public function __construct(B $b) { $this->_b = $b; } public function sayHello() { echo 'I am A'; $this->_b->sayHello(); } } echo '<pre>'; class Container { private $_map = array(); public function __set($k, $c) { $this->_map[$k] = $c; } public function __get($k) { if (!isset($this->_map[$k])) throw new Exception('Undefined class'); return $this->build($this->_map[$k]); } private function build($classname) { if ($classname instanceof Closure) return $classname($this); $reflection = new ReflectionClass($classname); // 涉及php反射相關知識 // 檢查類是否可例項化, 排除抽象類abstract和物件介面interface if (!$reflection->isInstantiable()) throw new Exception("介面不能被例項化"); if ($reflection === null) throw new Exception('類未定義'); $constructor = $reflection->getConstructor(); if (is_null($constructor)) return new $classname; if (!$constructor->isPublic()) throw new Exception('類不能被例項化'); $parameters = $constructor->getParameters(); if ($parameters === null) return new $classname; // 遞迴解析構造引數 $dependencies = $this->_getDependency($parameters); // 建立一個類的新例項,給出的引數將傳遞到類的建構函式。 return $reflection->newInstanceArgs($dependencies); } private function _getDependency($parameters) { $dependencies = []; foreach ($parameters as $parameter) { $dependency = $parameter->getClass(); if (is_null($dependency)) { $dependencies[] = $this->_resolveClass($parameter); } else { $dependencies[] = $this->build($dependency->name); } } return $dependencies; } private function _resolveClass($parameter) { if ($parameter->isDefaultValueAvailable()) { return $parameter->getDefaultValue(); } throw new Exception('Unknow error'); } } $di = new Container(); $di->a = 'A'; $di->a->sayHello();
結果:
I am AI am BI am C