控制反轉( IoC)和依賴註入(DI)

来源:https://www.cnblogs.com/vinter/archive/2018/03/29/8670032.html
-Advertisement-
Play Games

控制反轉( IoC)和依賴註入(DI) tags: 容器 依賴註入 IOC DI 控制反轉 引言:如果你看過一些框架的源碼或者手冊,像是laravel或者tp5之類的,應該會提到容器,依賴註入,控制反轉等辭彙。或者是某些面試官會問到這類問題。希望這篇文章能讓你有所收穫。 1.1、IoC(控制反轉 I ...


控制反轉( IoC)和依賴註入(DI)

tags: 容器 依賴註入 IOC DI 控制反轉


引言:如果你看過一些框架的源碼或者手冊,像是laravel或者tp5之類的,應該會提到容器,依賴註入,控制反轉等辭彙。或者是某些面試官會問到這類問題。希望這篇文章能讓你有所收穫。

1.1、IoC(控制反轉 Inversion of Control)

簡述:控制反轉並不是一種技術,而是一種設計思想。通過控制反轉容器(以後稱容器),改變了原本某些對象運行時依賴其他對象資源時需要自己進行獲取(比如通過new ClassName),所造成的對象之間的強耦合(耦合的概念如果不理解,可以先去瞭解一下。)。

  所謂IoC,對於程式來說,就是構造了一個容器,比如在tp5中,這個容器叫Container,此容器來負責控制對象和對象間的關係。在一個對象中,如果要使用另外的對象,就必須得到它(自己new一個),這樣的話一個對象A和另一個對象B之間就有了很強的聯繫(也就是強耦合)。這種耦合體現在如果被依賴的資源類初始化的時候(也可能是其他時候)傳入的參數變化了,你要修改兩個類的代碼,舉例說明:
  
你本來用的是php本身的session機制,現在想改成也支持redis,併在初始化的時候增加一個參數來控制。這個時候你不止需要去修改類Session類的代碼,還要去修改類A的代碼。部分代碼如下

//原代碼
class Session{
    function __construct(){
        //balabala
    }
}

class A{
    protected $driver;
    function __construct(){
       $this->driver = new Session();
    }
}

//需要增加一種redis方式後修改為
class Session{
    protected $driver;
    function __construct(string $driver=''){
        if($driver === ''){
            //balabala
        }else if($driver === 'redis'){//增加了一種模式
            //balabala
        }else{
            //balabala
        }
        
    }
}

class A{
    protected $driver;
    function __construct(){
        $this->driver = new Session('redis');//我想使用redis了
    }
}

可以看到,不止我們修改了B的代碼,還要去修改A的代碼,這樣如果依賴關係多起來的話,每次修改A依賴的對象,可能要處理A中很多條代碼。會造成對象之間的強耦合。所以我們可以把A需要的東西,在A之前就創建出來,並通過構造函數參數傳遞給A。代碼如下

 class A{
    protected $driver;
    function __construct(A $a){
        //我想使用redis了
    }
}

$driver = new Session('redis');//我想使用redis了
$a = new A($driver)   

這種方法下更改A依賴的所有對象都通過構造方法或者其他方法的形式給A,這些對象本身機制更改的時候就無需修改A的代碼了。但是每次自己使用A的時候都去看看A需要些什麼在前面都new一遍,感覺上很low啊,不如我們搞一個管家(容器),如果發現你需要什麼,管家就給你什麼。這樣所依賴的類的創建都由容器來控制,也就是說控制對象創建的不再是引用它的對象,而是容器。對於某個具體的對象而言,以前是它控制其他對象,需要什麼自己處理,現在是所有對象都被容器控制,所以控制反轉是一種控制權的轉移。

1.2、DI(依賴註入 Dependency Injection Container)

  IoC的一個重點是在系統運行中,動態的向某個對象提供它所需要的其他對象。這一點是通過DI(Dependency Injection,依賴註入,或者叫依賴註入容器)來實現的。比如還是上面的例子,對象A需要操作Session,以前我們總是要在A中自己編寫代碼來獲得一個Session對象,有了 容器這個管家我們就只需要告訴容器,A中需要一個Session對象,至於這個Session對象怎麼構造,何時構造,A不需要知道。在系統運行時,容器會在適當的時候製造一個Session,通過構造方法註射到A當中,這樣就完成了對各個對象之間關係的控制,而且這種關係是松耦合的。
  A需要依賴 Session才能正常運行,而這個Session是由容器註入到A中的,依賴註入的名字就這麼來的。那麼DI是如何實現的呢? php有一個高級特性是反射(reflection),原理這裡大概說一下,

反射可以在php運行中,提取出關於類、方法、屬性、參數,註釋等的詳細信息,並可以動態的調用方法和類等。這種動態獲取的信息以及動態調用對象的方法的功能稱為反射API。

反射允許程式在運行的時候動態的生成對象、執行對象的方法、改變對象的屬性,容器就是通過反射來實現註入的。

總結:
控制反轉是說創建對象的控制權進行轉移,由原來的資源需求方,轉移到了容器,依賴註入是說本來是資源需求方依賴資源,現在資源需求方依賴於容器對資源的註入,可以看出來依賴註入和控制反轉說的其實是一個事情。

順便提一句,目前很多框架中都離不開反射功能。容器是一個典型的例子,容器在laravel和tp5中都是核心功能之一。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 寫在最前面:這篇博文是2篇文章組成,詳細介紹了Angularjs中的緩存以及緩存清理,文章由上海尚學堂轉載過來,歡迎大家閱讀和評論。轉載請註明出處,謝謝! 一個緩存就是一個組件,它可以透明地儲存數據,以便以後可以更快地服務於請求。多次重覆地獲取資源可能會導致數據重覆,消耗時間。因此緩存適用於變化性不 ...
  • 因為好長時間的懶惰和懈怠,好久沒有更新文章了,從現在開始我會按時更新一些自己總結的一些知識,和研究的東西,希望能讓大家從我這裡學到一點點的知識。 本文參考了張榮銘的javascript設計模式一書,算是自己對看了文章的總結吧,如果你想學習設計模式,可以去購買一本,學習一下,寫的非常好。 javaSc ...
  • 1 2 3 4 5 AV 6 7 8 9 註意:audio標簽設置controls="controls"才可以再頁面中顯示 10 IE9開始支持 11 12 13 不支持audio 14 ... ...
  • 參考:http://www.jb51.net/article/117191.htm 侵刪 css 部分 js 部分 調用 ...
  • /** * 描述:導出表格對應的excel文件 * 時間:2018-03-29 * 作者:任恩遠 * 調用示例: * onclick = "tableToExcel(tableId,fileName)" */ /** * 描述:導出表格對應的excel文件 * 時間:2018-03-29 * 作者: ...
  • SnailDev.GifMaker 一個生成gif並添加自定義字幕的工具 client 微信小程式 server nodejs + express 歡迎 star&fork 如果您有好的commit 也可以pull request Introduction 參考於sorry, 由@xtyxtyx編寫 ...
  • 先放在這裡,下班再寫 ...
  • 情景: 父組件中引入上傳附件的子組件:點擊組件可以分別上傳對應要求的圖片,子組件內部迴圈可創建多個模塊. 父組件傳入數組子組件迴圈來創建不同的組件模塊,所有事件都在子組件內部. 父組件頁面的上方同時有一個上傳圖片按鈕上傳圖片後會顯示在第一個模塊: 設想思路:點擊父組件中的按鈕觸發子組件中上傳方法: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...