1 <?php 2 3 //容器类装实例或提供实例的回调函数 4 class Container { 5 6 protected $bindings = []; 7 8 //绑定接口和生成相应实例的回调函数 9 public function bind($abstract, $concrete=null, $shared=false) { 10 11 //如果提供的参数不是回调函数,则产生默认的回调函数 12 if(!$concrete instanceof Closure) { 13 $concrete = $this->getClosure($abstract, $concrete); 14 } 15 16 $this->bindings[$abstract] = compact('concrete', 'shared'); 17 } 18 19 //默认生成实例的回调函数 20 protected function getClosure($abstract, $concrete) { 21 22 return function($c) use ($abstract, $concrete) { 23 $method = ($abstract == $concrete) ? 'build' : 'make'; 24 return $c->$method($concrete); 25 }; 26 27 } 28 29 public function make($abstract) { 30 $concrete = $this->getConcrete($abstract); 31 32 if($this->isBuildable($concrete, $abstract)) { 33 $object = $this->build($concrete); 34 } else { 35 $object = $this->make($concrete); 36 } 37 38 return $object; 39 } 40 41 protected function isBuildable($concrete, $abstract) { 42 return $concrete === $abstract || $concrete instanceof Closure; 43 } 44 45 //获取绑定的回调函数 46 protected function getConcrete($abstract) { 47 if(!isset($this->bindings[$abstract])) { 48 return $abstract; 49 } 50 51 return $this->bindings[$abstract]['concrete']; 52 } 53 54 //实例化对象 55 public function build($concrete) { 56 57 if($concrete instanceof Closure) { 58 return $concrete($this); 59 } 60 61 $reflector = new ReflectionClass($concrete); 62 if(!$reflector->isInstantiable()) { 63 echo $message = "Target [$concrete] is not instantiable"; 64 } 65 66 $constructor = $reflector->getConstructor(); 67 if(is_null($constructor)) { 68 return new $concrete; 69 } 70 71 $dependencies = $constructor->getParameters(); 72 $instances = $this->getDependencies($dependencies); 73 74 return $reflector->newInstanceArgs($instances); 75 } 76 77 //解决通过反射机制实例化对象时的依赖 78 protected function getDependencies($parameters) { 79 $dependencies = []; 80 foreach($parameters as $parameter) { 81 $dependency = $parameter->getClass(); 82 if(is_null($dependency)) { 83 $dependencies[] = NULL; 84 } else { 85 $dependencies[] = $this->resolveClass($parameter); 86 } 87 } 88 89 return (array)$dependencies; 90 } 91 92 protected function resolveClass(ReflectionParameter $parameter) { 93 return $this->make($parameter->getClass()->name); 94 } 95 96 } 97 98 99 class Traveller { 100 101 protected $trafficTool; 102 103 public function __construct(Visit $trafficTool) { 104 $this->trafficTool = $trafficTool; 105 } 106 107 public function visitTibet() { 108 $this->trafficTool->go(); 109 } 110 111 } 112 113 interface Visit { 114 public function go(); 115 } 116 117 class Train implements Visit { 118 119 public function go() { 120 echo "go to Tibet by train !!!"; 121 } 122 123 } 124 125 $app = new Container(); 126 $app->bind("Visit", "Train"); 127 $app->bind("traveller", "Traveller"); 128 129 130 $tra = $app->make("traveller"); 131 $tra->visitTibet();