依赖
1.举例: 人开车,需要一辆车,车子能够正常运行,必须有轮子。
依赖关系就是人依赖于车,车依赖于轮子。分别建立以下的三个类
车轮
class Wheel
{
public function create()
{
echo '正在造轮子';
}
}
汽车
class Car
{
private $wheel;
public function __construct(Wheel $wheel)
{
$this->wheel = $wheel;
}
public function run()
{
$this->wheel->create();
echo '车发动机已经启动好,准备随时出发';
}
}
人
class Human
{
private $car;
public $instance;
public function __construct(Car $car)
{
$this->car = $car;
}
public function drive()
{
$this->car->run();
echo '人正在开车';
}
}
传统的调用方式是:
$wheel=new Wheel();
$car=new Car($wheel);
$human=new Human($car);
$human->driver();
通过构造函数一层一层的创建对象但是如果出现了某一个类进行修改的比较多,那么对于这种紧耦合的修改起来特别麻烦。
注入
class Ioc
{
//key 类名 value 闭包函数
public static $registry = [];
//向数组中存放函数
public static function bind($name, callable $reslover)
{
static::$registry[$name] = $reslover;
}
//获取存放的函数的返回值
public static function make($name)
{
if (isset(static::$registry[$name])) {
$reslover = static::$registry[$name];
return $reslover();
//以上两行代码也可以使用以下的来进行代替
//return call_user_func(static::$registry[$name]);
}
}
}
//最直白的解释就是:bind向容器中添加对象,make从容器中获取对象。
调用方式:
//自动加载刚才的三个类
function __autoload($className)
{
$file = $className . '.php';
if (is_file($file)) {
require_once($file);
}
}
//绑定到容器上
Ioc::bind('wheel', function () {
return new Wheel();
});
Ioc::bind('car', function () {
return new Car(Ioc::make('wheel'));
});
Ioc::bind('human', function () {
return new Human(Ioc::make('car'));
});
$info = Ioc::make('human');
$info->drive();
通过以上我们发现这样子虽然简化了new的过程,但是挨个进行bind同样也是要花费我们大量的时间,那么接下来就对这个容器进行改造,让容器自己根据我们传入的类名创建我们需要的对象。
1.首先要修改的地方就是make里面的返回方法,这里直接通过一个build方法实现了反射获取类的实例(不懂反射的请自行百度)
return self::build($name);
2.重点在build函数里面
//如果是匿名函数直接返回调用
if ($className instanceof Closure) {
return $className();
}
//利用反射的方式进行实例化
$reflector = new ReflectionClass($className);
//检查类是否可以被实例化
if ($reflector->isInstantiable()) {
//1.获取构造函数
$constructor = $reflector->getConstructor();
// 若无构造函数,直接实例化并返回
if (is_null($constructor)) {
return new $className;
}
// 取构造函数参数,通过 ReflectionParameter 数组返回参数列表
$parameters = $constructor->getParameters();
// 递归解析构造函数的参数
$dependencies = self::getDependencies($parameters);
// 创建一个类的新实例,给出的参数将传递到类的构造函数。
return $reflector->newInstanceArgs($dependencies);
}
调用方式和之前一样
具体代码在我上传的资源