<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] # DI DI就是常說的依賴注入,那么究竟什么是依賴注入呢? 打個比方,電腦(非筆記本哈)需要鍵盤和鼠標我們才能進行操作,這個‘需要’換句話說就是‘依賴’鍵盤和鼠標。 那么,相應的,一個類需要另一個類才能進行作業,那么這也就是依賴。 看一段代碼: ``` class Computer { protected $keyboard; public function __construct() { $this->$keyboard = new Keyboard(); } } 這里的Computer類依賴了鍵盤類。 ``` 好,既然我們已經知道了什么是依賴,那么什么是注入呢? 我們改造一下上面的代碼: ``` class Computer { protected $keyboard; public function __construct(Keyboard $keyboard) { $this->$keyboard = $keyboard; } } $computer = new Computer(new Keyboard()); 這里的Computer類依賴注入了Keyboard類。 ``` 關于依賴注入,我的理解是: > 所需要的類通過參數的形式傳入的就是依賴注入。 理解了依賴注入,我們可以接著理解IOC。 # IOC IOC是什么呢? 中文叫控制反轉。啥意思呢? 這個看明白了DI后就能很容易的理解了。 通過DI我們可以看到,一個類所需要的依賴類是由我們主動實例化后傳入類中的。 控制反轉和這個有什么關系呢? > 控制反轉意思是說將依賴類的控制權交出去,由主動變為被動。 看一段laravel代碼: ``` namespace App\Http\Controllers; use Illuminate\Http\Request; class SessionController extends Controller { public function login(Request $request) { //這就是IOC,我們不需要主動傳入類了一切由laravel去實現 } } ``` 看到這你可能有疑問了,這是怎么實現的呢? 這就是靠服務容器了,請往下接著看。 # 服務容器 看了很多文章,我一致認為服務容器就是一種設計模式。 > 它的目的就是解耦依賴。 這里我們再從頭至尾的看一遍,怎么一步步演化出服務容器。 依然是電腦的例子,我們知道電腦依賴鍵盤鼠標,可是鍵盤鼠標也有很多種呀。 先看一個最原始的代碼例子: ``` class Computer { protected $keyboard; public function __construct($type = null) { switch($type) { case 'common': $this->keyboard = new CommonKeyboard(); break; case 'awesome': $this->keyboard = new AweSomeKeyboard(); break; default: $this->keyboard = new Keyboard(); break; } } } ``` 或許你一眼就看出了問題在哪。 如果我們又要增加一鐘鍵盤,那我們又得對這個類進行修改。這樣下去,這個類會變得龐大且耦合程度過高。 那么我們可以怎么修改呢? - 工廠模式 這樣我們可以避免直接的修改Computer類。 ``` 簡單工廠 class Factory { public static function getInstance($type){ switch($type) { case 'common': $this->keyboard = new CommonKeyboard(); break; case 'awesome': $this->keyboard = new AweSomeKeyboard(); break; default: $this->keyboard = new Keyboard(); break; } } } class Computer { protected $keyboard; public function __construct($type = null) { $this->keyboard = Factory::getInstance($type); } } ``` 這樣使用簡單工廠模式后,我們后續的修改可以不用對Computer類進行操作而只要修改工廠類就行了。這就相當于對Computer類進行了解耦。 Computer類雖不在依賴那些鍵盤類了,但是卻變為依賴工廠類了。 后續添加新類型的鍵盤就必須對工廠類進行修改。 所以這個工廠類還不能很好的滿足要求,我們知道電腦對鍵盤的接口都是一致的,鍵盤必須實現這一接口才能被電腦識別,那我們對Computer和Keyboard類進行修改。 - DI(依賴注入) ``` interface Board { public function type(); } class CommonBoard implements Board { public function type(){ echo '普通鍵盤'; } } class MechanicalKeyboard implements Board { public function type(){ echo '機械鍵盤'; } } class Computer { protected $keyboard; public function __construct (Board $keyboard) { $this->keyboard = $keyboard; } } $computer = new Computer(new MechanialKeyBoard()); ``` 可是這樣也有問題,如果我們后續對這臺電腦使用的鍵盤不滿意要進行替換呢? 我們又回到原點了,必須去修改傳入的鍵盤類。 能不能做成可配置的呢? - IOC服務容器(超級工廠) ``` class Container { protected $binds; protected $instances; public function bind($abstract, $concrete) { if ($concrete instanceof Closure) { $this->binds[$abstract] = $concrete; } else { $this->instances[$abstract] = $concrete; } } public function make($abstract, $parameters = []) { if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } array_unshift($parameters, $this); return call_user_func_array($this->binds[$abstract], $parameters); } } ``` 這就是一個簡單的IOC服務容器。 這個怎么解決我們上述的問題呢? ``` $container = new $container; $container->bind('Board', function($container){ return new CommonBoard; }); $computer->bind('Computer',function($container,$module){ return new Computer($container->make($module)); }); $computer = $container->make('Computer',['Board']); ``` 這里生產出來的Computer類就是一個使用普通鍵盤的電腦類了。 解釋一下代碼: ``` bind(name,function($container){ return new Name; }) 這里的name和Name之間的關系是: 當我需要name類的時候你就給我實例化Name類。 make(name)方法是對name進行生產返回一個實例。 ``` 如果我們要更換鍵盤怎么辦呢? ``` $container->bind('Board', function($container){ return new MechanicalBoard; }); $computer->bind('Computer',function($container,$module){ return new Computer($container->make($module)); }); $computer = $container->make('Computer',['Board']); ``` 只要對bind綁定的Board類的實現進行修改,我們就可以很容易替換掉鍵盤了。這就是一個服務容器。 對服務容器進行一個理解: > 容器就是一個裝東西的,好比碗。而服務就是這個碗要裝的飯呀,菜呀,等等東西。當我們需要飯時,我們就能從這個碗里拿到。如果你想在飯里加點菜(也就是飯依賴注入了菜),我們從碗里直接拿飯就可以了,而這些依賴都由容器解決了(這也就是控制反轉)。 我們需要做的就是對提供的服務進行維護。 我們看一段真實的在laravel框架上能跑的代碼: [代碼](https://implode.io/4mT8O4) 當然laravel框架的服務容器比這里的要復雜很多了,但我們明白了它的使用目的以及使用場景就不難去入手laravel了。 PS: 個人微信公眾號'buger'。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看