zoukankan      html  css  js  c++  java
  • 依赖注入(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有关依赖注入的文章可以自行搜索。

  • 相关阅读:
    安装VMtools vim编辑器的使用 压缩包命令 Linux下的用户管理 (第三天)
    VM虚拟机安装 常用Linux命令 网卡配置 (第二天)
    数据库的交互模式 常用的dos命令 (第一天)
    Validate US Telephone Numbers FreeCodeCamp
    Arguments Optional FreeCodeCamp
    Everything Be True FreeCodeCamp
    Binary Agents FreeCodeCamp
    Steamroller FreeCodeCamp
    Drop it FreeCodeCamp
    Smallest Common Multiple FreeCodeCamp
  • 原文地址:https://www.cnblogs.com/orlion/p/4797422.html
Copyright © 2011-2022 走看看