PHP 依赖注入,依赖反转 (IOC-DI)

<?php
/**
 * 依赖注入 IOC DI
 * 参考文章
 * https://segmentfault.com/a/1190000002411255
 * https://segmentfault.com/a/1190000002424023
 */

/**
 * IOC
 * 控制反转 Inversion of Control
 * 依赖关系的转移
 * 依赖抽象而非实践
 * 比较实用的注入方式有三种
 * Setter injection 使用setter方法
 * Constructor injection 使用构造函数
 * Property Injection 直接设置属性
 */

// IOC 栗子
// 假设一个储存业务

// 定义接口 业务需求一个数据储存 到rides 或者 mysql 中
interface SaveIO {
    public function set ();
}
// 定义两种储存方式 并继承(implements)SaveIO 接口
// rides
class RidesClass implements SaveIO {
    public function set () {
        echo 'rides_save'.PHP_EOL;
    }
}
// mysql
class MysqlClass implements SaveIO {
    public function set (){
        echo 'mysql_save'.PHP_EOL;
    }
}

// 高层业务
class Business {
    private $myBusiness;
    public function __construct ($ioc) {
        $this->myBusiness = $ioc;
    }
    public function save () {
        $this->myBusiness->set();
    }
    // 替换依赖
    public function replaceIOC ($ioc) {
        $this->myBusiness = $ioc;
    }
}
echo 'IOC------'.PHP_EOL;
$bus = new Business(new RidesClass());
$bus->save(); // 输出rides_save

// 替换成其他依赖
$bus->replaceIOC(new MysqlClass());
$bus->save(); // 输出 mysql_save

/**
 * DI
 * 依赖注入 Dependency Injection
 * 容器自动根据配置,将依赖注入指定对象
 * 管理应用程序中的『全局』对象(包括实例化、处理依赖关系)。
 * 可以延时加载对象(仅用到时才创建对象)。
 * 促进编写可重用、可测试和松耦合的代码。
 */
// 首先需要一个容器
class ConComponent {
    protected $_di = array();
    // 注册 依赖 让依赖存储在$_di 存储形式 $_di->['服务名称']->Closure
    public function register ($name,$service) {
        $this->_di[$name] = $service;
    }

    /**
     * public function save ($name)
     * 高层业务,可以另外拓展一个类,不要放在容器里
     * (这里只是一个简易的写法,但是不要这样写)
     * 实现 class{
     * $构造函数=容器返回依赖
     * 高层业务根据需求
     * 通过$_di[className]()创建依赖类
     * 通过$_di[className]()->实现业务
     * }
     * @param $name
     */
    public function save ($name) {
       $this->_di[$name]()->set();
    }
}
/*
 * 重复利用 RedisClass MysqlClass
 * 注册依赖
 * */
$component = new ConComponent(); // 创建容器

/*
 * 注册依赖
 * @param name 依赖的名称
 * @param function(){} 是一个闭包(closure)
 * 所以只有在我们调用一次 $component->_di[name]
 * 才会创建一个依赖对象 实现需时创建
 * */
$component->register('RedisClass',function () {
    return new RidesClass();
});
$component->register('MysqlClass',function () {
    return new MysqlClass();
});
echo 'di----'.PHP_EOL;
$component->save('RedisClass'); // 输出rides_save
$component->save('MysqlClass'); // 输出Mysql_save

/**
 * AOP
 * Aspect-oriented programming
 * 面向方面编程
 * 无需修改任何一行程序代码,
 * 将功能加入至原先的应用程序中,
 * 也可以在不修改任何程序的情况下移除
 */

猜你喜欢

转载自my.oschina.net/u/3529405/blog/1821744