IoC 容器

原始版

  • 每次创造不同能力的超人,都需要修改Superman类
class Superman
{
    protected $power;

    public function __construct()
    {
        $this->power = new Fight(9, 100);
        // $this->power = new Force(45);
        // $this->power = new Shot(99, 50, 2);
        /*
        $this->power = array(
            new Force(45),
            new Shot(99, 50, 2)
        );
        */
    }
}

class Flight
{
    protected $speed;
    protected $holdtime;
    public function __construct($speed, $holdtime) {}
}

class Force
{
    protected $force;
    public function __construct($force) {}
}

class Shot
{
    protected $atk;
    protected $range;
    protected $limit;
    public function __construct($atk, $range, $limit) {}
}

//每次创造不同能力的超人,都需要修改Superman类
$superman = new Superman();

工厂

  • 创建超人,初始化时,就根据不同的需求,传入不同的参数,最后得到不同能力的超人,能力可以是多个,能力值任意改变
  • 不再依赖Superman类,但是依赖SuperModuleFactory工厂类,工厂类功能不够时,需要修改工厂类
class Factory
{
    public function activate($moduleName, $options)
    {
        switch ($moduleName) {
            case 'Fight':   return new Fight($options[0], $options[1]);
            case 'Force':   return new Force($options[0]);
            case 'Shot':    return new Shot($options[0], $options[1], $options[2]);
        }
    }
}

class Superman
{
    protected $power;

    public function __construct(array $modules)
    {
        // 初始化工厂
        $factory = new Factory;

        // 通过工厂提供的方法制造需要的模块
        foreach ($modules as $moduleName => $moduleOptions) {
            $this->power[] = $factory->activate($moduleName, $moduleOptions);
        }
    }
}

class Flight
{
    protected $speed;
    protected $holdtime;
    public function __construct($speed, $holdtime) {}
}

class Force
{
    protected $force;
    public function __construct($force) {}
}

class Shot
{
    protected $atk;
    protected $range;
    protected $limit;
    public function __construct($atk, $range, $limit) {}
}

// 创建超人,初始化时,就根据不同的需求,传入不同的参数,最后得到不同能力的超人,能力可以是多个,能力值任意改变
// 不再依赖Superman类,但是依赖SuperModuleFactory工厂类,工厂类功能不够时,需要修改工厂类
$superman = new Superman([
    'Fight' => [9, 100],
    'Shot' => [99, 50, 2]
]);

依赖注入

  • 只要遵循超能力工厂SuperFactoryInterface接口的规范,谁都可以创造不同的超能力工厂,超人创建不再依赖工厂
  • 但是每个超人都需要手动创建,效率低
class Superman
{
    protected $power;

    public function __construct(SuperFactoryInterface $module)
    {
        $this->power[] = $module->activate();

    }
}
//工厂接口
interface SuperFactoryInterface
{
    //返回超能力对象,如Fight,Shot
    public function activate();
}

//X-超能量工厂
class XPowerFactory implements SuperFactoryInterface
{
    public function activate()
    {
        return [new XPower([])];
    }
}
//终极炸弹工厂
class UltraBombFactory implements SuperFactoryInterface
{
    public function activate()
    {
        return [new UltraBomb([])];
    }
}

class XPower
{
    protected $x1;
    protected $x2;
    public function __construct($array) {}
}

class UltraBomb
{
    protected $u;
    protected $ul;
    public function __construct($array) {}
}

//只要遵循超能力工厂SuperFactoryInterface接口的规范,谁都可以创造不同的超能力工厂,超人创建不再依赖工厂
//但是每个超人都需要手动创建

//X-超能量超人
$XPower = new XPowerFactory();
$superman1 = new Superman($XPower);

//终极炸弹超人
$UltraBomb = new UltraBombFactory();
$superman2 = new Superman($UltraBomb);

Ioc容器

  • 向容器中添加创建超人的闭包 ,只有在真正的生产(make) 操作被调用执行时,才会触发。
  • 当有新的需求,只需另外绑定一个“生产闭包”即可。
  • 1条指令,就可以创建1个超人
class Superman
{
    protected $power;

    public function __construct(SuperFactoryInterface $module)
    {
        $this->power[] = $module->activate();

    }
}
//工厂接口
interface SuperFactoryInterface
{
    //返回超能力对象,如Fight,Shot
    public function activate();
}

//X-超能量工厂
class XPowerFactory implements SuperFactoryInterface
{
    public function activate()
    {
        return [new XPower([])];
    }
}
//终极炸弹工厂
class UltraBombFactory implements SuperFactoryInterface
{
    public function activate()
    {
        return [new UltraBomb([])];
    }
}

class XPower
{
    protected $x1;
    protected $x2;
    public function __construct($array) {}
}

class UltraBomb
{
    protected $u;
    protected $ul;
    public function __construct($array) {}
}

class Container
{
    protected $binds;//这里存创建超人的闭包,格式,"XPower"=>"创建XPower超人的闭包", "UltraBomb"=>"创建UltraBomb超人的闭包"

    //$abstract,超人的名称
    //$concrete,创建超人的闭包
    public function bind($abstract, $concrete)
    {
        //必须是闭包才存下来
        if ($concrete instanceof Closure) {
            $this->binds[$abstract] = $concrete;
        }
    }

    public function make($abstract, $parameters = [])
    {
        //存在这个闭包,就去执行
        if (isset($this->binds[$abstract])) {
            return call_user_func_array($this->binds[$abstract], $parameters);
        }
    }
}

// 向该超级工厂添加 xpower 超能力模组的生产脚本
$container->bind('xpower', function($container) {
    //X-超能量超人
    $XPower = new XPowerFactory();
    $superman = new Superman($XPower);
    return $superman;
});

// 向该超级工厂添加 终极炸弹 超能力模组的生产脚本
$container->bind('UltraBomb', function($container) {
    //终极炸弹超人
    $UltraBomb = new UltraBombFactory();
    $superman = new Superman($UltraBomb);
    return $superman;
});

//向容器中添加创建超人的闭包 ,只有在真正的生产(make) 操作被调用执行时,才会触发。
//当有新的需求,只需另外绑定一个“生产闭包”即可。
//1条指令,就可以创建1个超人

//正的 IoC 容器会根据类的依赖需求,自动在注册、绑定的一堆实例中搜寻符合的依赖需求,并自动注入到构造函数参数中去。Laravel 框架的服务容器正是这么做的
//这种自动搜寻依赖需求的功能,是通过 反射(Reflection) 实现的

//X-超能量超人
$xpower_1 = $container->make('xpower', []);
$xpower_2 = $container->make('xpower', []);

//终极炸弹超人
$UltraBomb_1 = $container->make('UltraBomb', []);
$UltraBomb_2 = $container->make('UltraBomb', []);
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!