再說php依賴注入

來源:互聯網
上載者:User

標籤:現實生活   參數   cti   查詢   管理   決定   通過   stat   最好   

前段時間,有朋友問我yii2的依賴注入是怎麼個玩法,好吧,

經常看到卻一直不甚理解的概念,這裡我再對自己認識的依賴注入深刻的表達下我的理解,依賴注入(DI)以及控制器反轉(Ioc)。 依賴注入就是組件通過構造器,方法或者屬性欄位來擷取相應的依賴對象。

舉個現實生活中的例子來理解, 比如我要一把菜刀 如何獲得
1.可以自己造一把,對應new一個。
2.可以找生產菜刀的工廠去買一把,對應原廠模式。
3.可以打電話 讓店家送貨上門,對應依賴注入

依賴注入(DI)的概念雖然聽起來很深奧,但是如果你用過一些新興的php架構的話,對於DI一定不陌生,因為它們多多少少都用到了依賴注入來處理類與類之間的依賴關係。

php中傳遞依賴關係的三種方案

其實要理解DI,首先要明白在php中如何傳遞依賴關係。 
第一種方案,也是最不可取的方案,就是在A類中直接用new關鍵詞來建立一個B類,如下代碼所示:

<?phpclass A{    public function __construct()    {        $b = new B();    }}

為什麼這種方案不可取呢?因為這樣的話,A與B就耦合在了一起,也就是說A類無法脫離B類工作。 
第二種方案就是在A類的方法中傳入需要的B類,如下代碼所示:

<?phpclass A{    public function __construct(B $b)    {    }}

這種方法比第一種方案有了改進,A類不必與B類捆綁在一起,只要傳入的類滿足A類的需求,也可以是C類,也可以是D類等等。 
但是這種方案的弊端在於如果A類依賴的類較多,參數列表會很長,容易發生混亂。 
第三種方案是使用set方法傳入,如下代碼所示:

<?phpclass A{    public function setB(B $b)    {        $this->b = $b;    }}

這種方案同樣存在和第二種方案一樣的弊端,當依賴的類增多時,我們需要些很多很多的set方法。

這時我們在想如果有一個專門的類(或者說一個容器)可以幫我們管理這些依賴關係就好了。

一個簡單的依賴注入的例子

如下代碼來自twittee:

<?phpclass Container { private $s=array(); function __set($k, $c) { $this->s[$k]=$c; } function __get($k) { return $this->s[$k]($this); }}

有了container類之後我們可以怎樣管理A與B之間的依賴關係呢,用代碼說話吧:

<?phpclass A{    private $container;    public function __construct(Container $container)    {        $this->container = $container;    }    public function doSomeThing()    {        //do something which needs class B        $b = $this->container->getB();        //to do     }}

再將B類注入到容器類中:

$c = new Container();$c->setB(new B());

還可以傳入一個匿名函數,這樣B類就不會在傳入時就立即執行個體化,而是在真正調用時才完成執行個體化的工作:

$c = new Container();$c->setB(function (){    return new B();});

這裡舉的只是一個很簡單的例子,在實際中,容器類要考慮的有很多,比如消極式載入等等。

再比如我是一個演員,我不可能要求某個導演,我要演某某劇的男一號,相反,導演可以決定讓誰來演。而我們的object就是這個演員。

注入的幾個途徑:
1.construct注入

<?phpclass Book {   private $db_conn;    public function __construct($db_conn) {       $this->db_conn = $db_conn;   }}

但是如果依賴過多,那麼在構造方法裡必然傳入多個參數,三個以上就會使代碼變的難以閱讀。

2.set注入

<?php  $book = new Book();  $book->setdb($db);  $book->setprice($price);  $book->set_author($author);?>

代碼很清晰,但是當我們需要注入第四個依賴時,意味著又要增加一行。

比較好的解決辦法是 建立一個class作為所有依賴關係的container,在這個class中可以存放、建立、擷取、尋找需要的依賴關係

<?phpclass Ioc {   protected $db_conn;   public static function make_book() {       $new_book = new Book();       $new_book->set_db(self::$db_conn);       //...       //...       //其他的依賴注入       return $new_book;   }}

此時,如果擷取一個book執行個體,只需要執行$newone = Ioc::makebook();

以上是container的一個具體執行個體,最好還是不要把具體的某個依賴注入寫成方法,採用registry註冊,get擷取比較好。

<?phpclass Ioc {/*** @var 註冊的依賴數組*/    protected static $registry = array();    /**    * 添加一個resolve到registry數組中    * @param  string $name 依賴標識    * @param  object $resolve 一個匿名函數用來建立執行個體    * @return void    */   public static function register($name, Closure $resolve)   {      static::$registry[$name] = $resolve;   }    /**     * 返回一個執行個體     * @param  string $name 依賴的標識     * @return mixed     */   public static function resolve($name)   {       if ( static::registered($name) )       {          $name = static::$registry[$name];          return $name();       }       throw new Exception(‘Nothing registered with that name, fool.‘);   }   /**    * 查詢某個依賴執行個體是否存在    * @param  string $name id    * @return bool     */   public static function registered($name)   {      return array_key_exists($name, static::$registry);   }}

現在就可以通過如下方式來註冊和注入一個依賴

<?php$book = Ioc::registry(‘book‘, function(){$book = new Book;$book->setdb(‘...‘);$book->setprice(‘...‘);return $book;}); //注入依賴$book = Ioc::resolve(‘book‘);?>

再說php依賴注入

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.