• 依赖注入(DI)与服务容器(IoC)


    参考文章:http://www.yuansir-web.com/2014/03/20/%E7%90%86%E8%A7%A3php-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5laravel-ioc%E5%AE%B9%E5%99%A8/?preview

    我们在建一个类时,在类的内部有可能会用到另外一个对象实例举个栗子:

    class User{
        public function getUser(){
            $db = new DB(); // 这里产生了对数据库连接类的依赖
            $db->select('select username form user..');
            ...
        }
    }

    当我们修改了DB这个类时肯定要回来修改User这个类,可以想象DB类肯定不是只用在User类中,一个项目中要有许多类要用到DB类,如果DB类修改了(举个不恰当的例子:DB这个类改名了)那必须要把项目中所有用到db类的类都要作修改。

    这个时候可以这样解决

    class User{
        public function getUser(DB $db){
            //$db = new DB(); // 依赖消失
            $db->select('select username form user..');
            ...
        }
    }

    这个时候想调用getUser方法就必须要“注入”$db。

    实际中我们的User类肯定不是只会用到getUser这个方法的,还有可能会用到getUsername、getUserAge、getUserSex...等等,难道我们要为每个方法都加一个$db参数吗?当然不可能所以我们再来完善一下这个User类:

    class User{
        private $db;
        //*
        public function __construct(DB $db){
            $this->db = $db;
        }
        /*/
        public function getDb(DB $db){
            $this->db = $db;
        }
        //*/
        public function getUser(){
            $this->db->select('select username form user..');
            ...
        }
        public function getUserAge(){
            $this->db->select('select userage form user..');
            ...
        }
        public function getUserSex(){
            $this->db->select('select usersex form user..');
            ...
        }
    }


    可以看到我们可以在构造器和getDb方法中注入$db。

    好了,我们已经实现“依赖反转”了!但是!!!假如我们User类还需要其他类呢?举个很不恰当的牵强的栗子:

    我们把username放到memcache 中,把userage放到session中,把usersex放到redis中(这。。。很不实际)那我们的类就变成这个样子了

    class User{
        private $db;
        private $mem;
        private $redis;
      ...
    public function __construct(DB $db , Mem $mem , Redis $redis , Session $session ...... ){ $this->db = $db; $this->mem = $mem; $this->redis = $redis; } public function getUser(){ $this->db->select('select username form user..'); ... } public function getUserAge(){ $this->mem->get('userage'); ... } public function getUserSex(){ $this->redis->get('usersex'); ... } }

    要在控制器里放那么多实例。而且如果要使用User类的话还有实例这么多存贮类,不累吗?代码肯定一团糟!

    这个时候可以用一个工厂来“完善”一下:

    class UserFactory{
        public static function getUserObj(){
            $db = new DB();
            $mem = new Mem();
            ...
            $user = new ($db , $mem , ...);
            return $user;
        }
    }

    这样就好看多了,但是!!!然并卵,我们还是要实例化各个存储类(db,mem,redis。。。)

    现在该服务容器(IoC)登场了:

    class User{
        private $IoC;
        public function __construct(IoC $IoC){
            $this->IoC = $IoC;
        }
        
        public function getUser(){
            $this->IoC->get('db')->select('select username form user..');
            ...
        }
        public function getUserAge(){
            $this->IoC->get('mem')->get('userage');
            ...
        }
        public function getUserSex(){
            $this->IoC->get('redis')->get('usersex');
            ...
        }
    }
    
    $IoC = new IoC();
    // 这里使用了闭包函数,$di->set的时候实际上并没有实例化,
    // 而是在$di->get()的时候才执行了匿名函数并将对象返回。
    $IoC->set('db' , function(){
        return new DB(...);
    });
    $IoC->set('mem' , funciton(){
        return new Mem(...);
    });
    $IoC->set('redis' , funciton(){
        return new Redis(...);
    });
    $user = new User($IoC);

    大功告成!!!!!!

    DI与IoC就是这么简单。

    分享几个链接:

    symfony中服务容器:

    http://www.cnblogs.com/Seekr/archive/2012/06/19/2554934.html

    听 Fabien Potencier 谈Symfony2 之 《What is Dependency Injection ?》

    http://www.cnblogs.com/Seekr/archive/2012/06/20/2556463.html

    另外还有laravel、struts2、spring有关依赖注入的文章可以自行搜索。

  • 相关阅读:
    pthread_rwlock_rdlock和“No such file or directory”
    Thrift线程和状态机分析
    Haodoop RPC解析
    Thrift结构分析及增加取客户端IP功能实现
    StarUML 5.0问题解决:Failed to open the model file. Invalid file format.
    检测Linux系统是否支持某系统调用
    eclipse的thrift插件
    常见gcc编译问题解决方法集
    Thrift编译错误('::malloc' has not been declared)
    安装Android SDK Manager的“Failed to fetch refused”问题解决方法
  • 原文地址:https://www.cnblogs.com/orlion/p/4797422.html
Copyright © 2020-2023  润新知