Ioc容器实现

看了篇讲解laravel Ioc容器的文章,自己照着文章实践了下,注释部分是自己的理解

interface SuperModuleInterface{
    public function activate();
}

class XPower implements SuperModuleInterface {
    
    protected $range;
    protected $cd;
    
    public function __construct($range=0,$cd=0) {
        $this->range = $range;
        $this->cd = $cd;
    }
    
    public function activate(){ print_r($this);}
}

class Fly implements SuperModuleInterface {
  
    protected $height;
    protected $times;
    
    public function __construct($height=0,$times=0) {
        $this->height = $height;
        $this->times = $times;
    }
    
    public function activate(){ print_r($this);}
}

class SuperModuleFactory{
    public function makeModule($moduleName,$options){
        switch($moduleName){
            case 'fly': return new Fly($options[0],$options[1]);
            case 'xpower': return new XPower($options[0],$options[1]);
        }
    }
}


class Container{

    protected $binds;
    protected $instances;

    public function bind($abstract,$concrete){
        if($concrete instanceof Closure){
            $this->binds[$abstract]=$concrete;
        }else{
            $this->instances[$abstract]=$concrete;
        }
    }
    
    public function make($abstract,$parmeters=[]){
        if(isset($this->instances[$abstract])){
            return $this->instances[$abstract];
        }
        
        array_unshift($parmeters,$this);
        
        #调用回调函数,并把自身作为第一个参数传入
        return call_user_func_array($this->binds[$abstract],$parmeters);
        
    }
    
}

class Superman{

    protected $power;
    
    /**
     * 第三代构造器-依赖注入
     * @param SuperModuleInterface $module 超能力模块
     */
    public function __construct(SuperModuleInterface $module) {
        $this->power=$module;
    }
    
    /**
     * 第二代构造器-依赖工厂
     * @param $modules
     */
    //public function __construct($modules) {
    //    $factory=new SuperModuleFactory();
    //    foreach($modules as $moduleName =>$options){
    //        $this->power[]=$factory->makeModule($moduleName,$options);
    //    }
    //
    //}
    
    /**
     * 第一代构造器-依赖具体实现类
     */
    //public function __construct() {
    //    $this->power[]=new XPower(100,11);
    //    $this->power[]=new Fly(10000,3600);
    //}
    
    public function attack(){
        $powers=is_array($this->power)?$this->power:array($this->power);
        foreach($powers as $p){
            $p->activate();
        }
    }
}

$container=new Container();

#此处这个写保证每次注入的都是一个新的对象
#如果写成    $container->bind('XPower',new XPower());
#那么每次注入的都将是同一个对象,即注入的对象在各个实例中共享[传参是对象时传递的是引用,不是复制]
$container->bind('XPower',function($container,$range,$cd){
    return new XPower($range,$cd);
});

$container->bind('Fly',function($container,$height,$times){
    return new Fly($height,$times);
});

$container->bind('Superman',function($container,$moduleName, ...$arg){
    return new Superman($container->make($moduleName,$arg));
});

$superman_1=$container->make('Superman',['XPower',1,2]);
$superman_2=$container->make('Superman',['Fly',5,6]);

echo '
';
$superman_1->attack();
echo PHP_EOL;
$superman_2->attack();

执行结果:

XPower Object
(
    [range:protected] => 1
    [cd:protected] => 2
)

Fly Object
(
    [height:protected] => 5
    [times:protected] => 6
)

你可能感兴趣的:(Ioc容器实现)