laravel 浅析依赖倒转、控制反转、IoC 容器、依赖注入

参考: https://learnku.com/articles/14145/rely-on-inversion-control-inversion-ioc-container-dependency-injection
今天看到 浅析依赖倒转、控制反转、IoC 容器、依赖注入 这篇文件,让自己初步了解这些概念。记录一下这篇 重写仿照 laravel 的 IOC 容器和依赖注入 的代码

<?php
class Boos{

    //领导依赖员工
    private $staff;

    //老板只需要告诉外部我需要什么样的人就好了,其它什么都不管,具体什么样的人交给外部处理。
    //用构造方法方式实现依赖注入
    public function __construct(Standard $staff){       
        $this->staff = $staff;
    } 

    public function task(){
        $this->staff->work();
    }
}

//招聘所设定的标准
interface Standard{
    public function work();
}

//员工需要依赖的标准
class StaffA implements Standard{
    public function work(){
        echo '雇员A有能力能够完成老板指定的工作';
    }
}

class StaffB implements Standard{
    public function work(){
        echo '雇员B有能力能够完成老板指定的工作';
    }
}

class Hr{

    private $binds = [];

    //接受不同员工的简历,并存起来  2、实例化后调用 bind 方法参数 
    // $contract = 'Standard', $concrete = 'StaffA'
    public function bind($contract,$concrete){
    	//等于 $this->binds['Standard'] = 'StaffA';
        $this->binds[$contract] = $concrete;
    }

    //询问老板选人的标准由哪些,并且从满足的简历中筛选人
    private function methodBindParams($className){
    	// 5、 根据第4步 调用的 methodBindParams 方法 参数 $className = 'Boos', 
    	// 	   这里进行实例化 reflect 类,并且传递参数 $className = 'Boos','__construct'
        $reflect = new reflect($className,'__construct');
        // 7、实例化完成后 调用 reflect 类的 bindParamsToMethod 方法并且返回
        return $reflect->bindParamsToMethod();
    }

    //将选好的工作人员交给老板 3、调用 make 方法 参数 'Boos'
    public function make($className){
    	// 4、调用 当前类里的 methodBindParams 方法,传递参数为 'Boos'
    	// 根据 第8步,最终 $methodBindParams = ['Boos' => [0 => ['staff', 'Standard']] ];
        $methodBindParams = $this->methodBindParams($className);
        // 9、 这里进行实例化 reflect 类,并且传递参数 $className = 'Boos','__construct'
        $reflect = new reflect($className,'__construct');
        // 10、调用 reflect 类的 make方法,
        // $this->binds = ['Standard'=> 'StaffA'];
        // $methodBindParams = ['Boos' => [0 => ['staff', 'Standard']] ];
        // 根据11步,这里最终返回的是 Boos的实例化
        return $reflect->make($this->binds,$methodBindParams);
    }
}

class reflect{
    private $className;

    private $methodName;
	// 6、根据第5步,实例化 reflect 类,也就是本类, 实例化后会先调用 __construct 构造方法
	// 并且传递的参数为 $className = 'Boos',$methodName = '__construct'
    public function __construct($className,$methodName){
        $this->className = $className;
        $this->methodName = $methodName;
    }

    //绑定参数到方法  8、根据第七步的调用 走此方法
    public function bindParamsToMethod(){

        $params = [];
		// 8续、实例化一个 ReflectionMethod 类,$this->className,$this->methodName参数根据
		// 第5步 实例化时传递的 $className = 'Boos',$methodName = '__construct'
		// 实际就时获取的 Boos类的 __construct 方法的详情
        $method  = new ReflectionMethod($this->className,$this->methodName);
		// 8续、根据上面这行代码 拿到的 __construct 方法详情,然后 getParameters 方法获取 
		// __construct 方法的参数,按顺序进行获取,返回的是个数组 所以这里进行foreach循环
        foreach ($method->getParameters() as $param) {
			// 8续、 $param->name 是 Boos 类的__construct的参数名称,Boos的
			// __construct(Standard $staff) 方法只有一个参数,这里循环只会循环一次
			// $param->getClass()->name 获取的是变量的对象声明,类型声明无法获取。
			// 最终 $param->name 为 'staff' , $param->getClass()->name 为 'Standard'
            $params[] =  [$param->name,$param->getClass()->name];
        }
		// 8续、然后返回,$this->className 为 'Boos',
		// $params 为 $params = [ 0 => ['staff', 'Standard'] ];
		// 最终为 ['Boos' => [0 => ['staff', 'Standard']] ];
        return [$this->className => $params];
    }
	
	// 11、根据第10步调用的本方法 make 并且传递的参数
	// $this->binds = ['Standard'=> 'StaffA'];
    // $methodBindParams = ['Boos' => [0 => ['staff', 'Standard']] ];
    public function make($bind,$methodBindParams){
        $args = [];
        foreach ($methodBindParams as $className => $params) {
            foreach ($params as $param) {
                list($paramName,$paramType) = $param;
				// 11续、 根据传递的参数循环,
				// new $bind[$paramType]()等于 new $bind['Standard']()
				// new $bind['Standard']() 等于 new StaffA();
				// 这里 $paramName 就是实例对象
                $paramName = new $bind[$paramType]();
				// 然后添加到 $args 数组中
                array_push($args, $paramName);
            }
        }
        // 11续、根据第9步,实例化本类的时候传递的参数 $className = 'Boos',
        // 所以这里获取的是 Boos 类详情
        $reflectionClass = new ReflectionClass($this->className);
        // 11续、这里进行 Boos 类实例化,并且把 $args 参数传递到 Boos类的构造函数
        // 根据上面的循环实例化,$args数组中的每个元素都是 一个实现了 Standard 接口的类
        // 根据 Boos 类的 __construct(Standard $staff) 类型声明 传递是没问题的
        // 最终返回的是  Boos类实例化
        return $reflectionClass->newInstanceArgs($args);
    }

}
// 1、实例化 Hr 类
$hr = new Hr();

//老板如果需要换工作人员,只需要绑定其它的工作人员即可。
//2、实例化后调用 bind 方法
$staff = $hr->bind('Standard','StaffA');
// 3、调用 make 方法 返回的是Boos类实例化,并且把 StaffA 传递进了Boos类的构造函数
// 根据第11步进行传递的
$boos = $hr->make('Boos');
// 12、终篇 然后这里调用 task()
// $this->staff->work();   $this->staff也就是 StaffA 的实例化,
// 在第11步进行传递进Boos类的构造函数
$boos->task();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值