Ioc原理理解

来源:https://www.cnblogs.com/SmileIven/archive/2018/08/24/9528980.html
-Advertisement-
Play Games

IoC理論的背景 我們都知道,在採用面向對象方法設計的軟體系統中,它的底層實現都是由N個對象組成的,所有的對象通過彼此的合作,最終實現系統的業務邏輯。 如果我們打開機械式手錶的後蓋,就會看到與上面類似的情形,各個齒輪分別帶動時針、分針和秒針順時針旋轉,從而在表盤上產生正確的時間。圖1中描述的就是這樣 ...


 IoC理論的背景

    我們都知道,在採用面向對象方法設計的軟體系統中,它的底層實現都是由N個對象組成的,所有的對象通過彼此的合作,最終實現系統的業務邏輯。

如果我們打開機械式手錶的後蓋,就會看到與上面類似的情形,各個齒輪分別帶動時針、分針和秒針順時針旋轉,從而在表盤上產生正確的時間。圖1中描述的就是這樣的一個齒輪組,它擁有多個獨立的齒輪,這些齒輪相互嚙合在一起,協同工作,共同完成某項任務。我們可以看到,在這樣的齒輪組中,如果有一個齒輪出了問題,就可能會影響到整個齒輪組的正常運轉。
    齒輪組中齒輪之間的嚙合關係,與軟體系統中對象之間的耦合關係非常相似。對象之間的耦合關係是無法避免的,也是必要的,這是協同工作的基礎。現在,伴隨著工業級應用的規模越來越龐大,對象之間的依賴關係也越來越複雜,經常會出現對象之間的多重依賴性關係,因此,架構師和設計師對於系統的分析和設計,將面臨更大的挑戰。對象之間耦合度過高的系統,必然會出現牽一發而動全身的情形。

耦合關係不僅會出現在對象與對象之間,也會出現在軟體系統的各模塊之間,以及軟體系統和硬體系統之間。如何降低系統之間、模塊之間和對象之間的耦合度,是軟體工程永遠追求的目標之一。為瞭解決對象之間的耦合度過高的問題,軟體專家Michael Mattson提出了IOC理論,用來實現對象之間的“解耦”,目前這個理論已經被成功地應用到實踐當中,很多的J2EE項目均採用了IOC框架產品Spring。

什麼是控制反轉(IoC)    

IOC是Inversion of Control的縮寫,多數書籍翻譯成“控制反轉”,還有些書籍翻譯成為“控制反向”或者“控制倒置”。 
    1996年,Michael Mattson在一篇有關探討面向對象框架的文章中,首先提出了IOC 這個概念。對於面向對象設計及編程的基本思想,前面我們已經講了很多了,不再贅述,簡單來說就是把複雜系統分解成相互合作的對象,這些對象類通過封裝以後,內部實現對外部是透明的,從而降低瞭解決問題的複雜度,而且可以靈活地被重用和擴展。IOC理論提出的觀點大體是這樣的:藉助於“第三方”實現具有依賴關係的對象之間的解耦,如下圖:

大家看到了吧,由於引進了中間位置的“第三方”,也就是IOC容器,使得A、B、C、D這4個對象沒有了耦合關係,齒輪之間的傳動全部依靠“第三方”了,全部對象的控制權全部上繳給“第三方”IOC容器,所以,IOC容器成了整個系統的關鍵核心,它起到了一種類似“粘合劑”的作用,把系統中的所有對象粘合在一起發揮作用,如果沒有這個“粘合劑”,對象與對象之間會彼此失去聯繫,這就是有人把IOC容器比喻成“粘合劑”的由來。
我們再來做個試驗:把上圖中間的IOC容器拿掉,然後再來看看這套系統:

我們現在看到的畫面,就是我們要實現整個系統所需要完成的全部內容。這時候,A、B、C、D這4個對象之間已經沒有了耦合關係,彼此毫無聯繫,這樣的話,當你在實現A的時候,根本無須再去考慮B、C和D了,對象之間的依賴關係已經降低到了最低程度。所以,如果真能實現IOC容器,對於系統開發而言,這將是一件多麼美好的事情,參與開發的每一成員只要實現自己的類就可以了,跟別人沒有任何關係!
    我們再來看看,控制反轉(IOC)到底為什麼要起這麼個名字?我們來對比一下:
    軟體系統在沒有引入IOC容器之前,如圖1所示,對象A依賴於對象B,那麼對象A在初始化或者運行到某一點的時候,自己必須主動去創建對象B或者使用已經創建的對象B。無論是創建還是使用對象B,控制權都在自己手上。
    軟體系統在引入IOC容器之後,這種情形就完全改變了,如圖3所示,由於IOC容器的加入,對象A與對象B之間失去了直接聯繫,所以,當對象A運行到需要對象B的時候,IOC容器會主動創建一個對象B註入到對象A需要的地方。
    通過前後的對比,我們不難看出來:對象A獲得依賴對象B的過程,由主動行為變為了被動行為,控制權顛倒過來了,這就是“控制反轉”這個名稱的由來。

 IOC的別名:依賴註入(DI)   

 2004年,Martin Fowler探討了同一個問題,既然IOC是控制反轉,那麼到底是“哪些方面的控制被反轉了呢?”,經過詳細地分析和論證後,他得出了答案:“獲得依賴對象的過程被反轉了”。控制被反轉之後,獲得依賴對象的過程由自身管理變為了由IOC容器主動註入。於是,他給“控制反轉”取了一個更合適的名字叫做“依賴註入(Dependency Injection)”。他的這個答案,實際上給出了實現IOC的方法:註入。所謂依賴註入,就是由IOC容器在運行期間,動態地將某種依賴關係註入到對象之中。

所以,依賴註入(DI)和控制反轉(IOC)是從不同的角度的描述的同一件事情,就是指通過引入IOC容器,利用依賴關係註入的方式,實現對象之間的解耦。
    我們舉一個生活中的例子,來幫助理解依賴註入的過程。大家對USB介面和USB設備應該都很熟悉吧,USB為我們使用電腦提供了很大的方便,現在有很多的外部設備都支持USB介面。

 IOC為我們帶來了什麼好處

     我們還是從USB的例子說起,使用USB外部設備比使用內置硬碟,到底帶來什麼好處?
     第一、USB設備作為電腦主機的外部設備,在插入主機之前,與電腦主機沒有任何的關係,只有被我們連接在一起之後,兩者才發生聯繫,具有相關性。所以,無論兩者中的任何一方出現什麼的問題,都不會影響另一方的運行。這種特性體現在軟體工程中,就是可維護性比較好,非常便於進行單元測試,便於調試程式和診斷故障。代碼中的每一個Class都可以單獨測試,彼此之間互不影響,只要保證自身的功能無誤即可,這就是組件之間低耦合或者無耦合帶來的好處。
     第二、USB設備和電腦主機的之間無關性,還帶來了另外一個好處,生產USB設備的廠商和生產電腦主機的廠商完全可以是互不相干的人,各乾各事,他們之間唯一需要遵守的就是USB介面標準。這種特性體現在軟體開發過程中,好處可是太大了。每個開發團隊的成員都只需要關心實現自身的業務邏輯,完全不用去關心其它的人工作進展,因為你的任務跟別人沒有任何關係,你的任務可以單獨測試,你的任務也不用依賴於別人的組件,再也不用扯不清責任了。所以,在一個大中型項目中,團隊成員分工明確、責任明晰,很容易將一個大的任務劃分為細小的任務,開發效率和產品質量必將得到大幅度的提高。
     第三、同一個USB外部設備可以插接到任何支持USB的設備,可以插接到電腦主機,也可以插接到DV機,USB外部設備可以被反覆利用。在軟體工程中,這種特性就是可復用性好,我們可以把具有普遍性的常用組件獨立出來,反覆利用到項目中的其它部分,或者是其它項目,當然這也是面向對象的基本特征。顯然,IOC不僅更好地貫徹了這個原則,提高了模塊的可復用性。符合介面標準的實現,都可以插接到支持此標準的模塊中。
     第四、同USB外部設備一樣,模塊具有熱插拔特性。IOC生成對象的方式轉為外置方式,也就是把對象生成放在配置文件里進行定義,這樣,當我們更換一個實現子類將會變得很簡單,只要修改配置文件就可以了,完全具有熱插撥的特性。
以上幾點好處,難道還不足以打動我們,讓我們在項目開發過程中使用IOC框架嗎?

IOC容器的技術剖析  

  IOC中最基本的技術就是“反射(Reflection)”編程,目前.Net C#、Java和PHP5等語言均支持,其中PHP5的技術書籍中,有時候也被翻譯成“映射”。有關反射的概念和用法,大家應該都很清楚,通俗來講就是根據給出的類名(字元串方式)來動態地生成對象。這種編程方式可以讓對象在生成時才決定到底是哪一種對象。反射的應用是很廣泛的,很多的成熟的框架,比如象Java中的Hibernate、Spring框架,.Net中 NHibernate、Spring.Net框架都是把“反射”做為最基本的技術手段。
    反射技術其實很早就出現了,但一直被忽略,沒有被進一步的利用。當時的反射編程方式相對於正常的對象生成方式要慢至少得10倍。現在的反射技術經過改良優化,已經非常成熟,反射方式生成對象和通常對象生成方式,速度已經相差不大了,大約為1-2倍的差距。
    我們可以把IOC容器的工作模式看做是工廠模式的升華,可以把IOC容器看作是一個工廠,這個工廠里要生產的對象都在配置文件中給出定義,然後利用編程語言的的反射編程,根據配置文件中給出的類名生成相應的對象。從實現來看,IOC是把以前在工廠方法里寫死的對象生成代碼,改變為由配置文件來定義,也就是把工廠和對象生成這兩者獨立分隔開來,目的就是提高靈活性和可維護性。
6 IOC容器的一些產品
    Sun ONE技術體系下的IOC容器有:輕量級的有Spring、Guice、Pico Container、Avalon、HiveMind;重量級的有EJB;不輕不重的有JBoss,Jdon等等。Spring框架作為Java開發中SSH(Struts、Spring、Hibernate)三劍客之一,大中小項目中都有使用,非常成熟,應用廣泛,EJB在關鍵性的工業級項目中也被使用,比如某些電信業務。
    .Net技術體系下的IOC容器有:Spring.Net、Castle等等。Spring.Net是從Java的Spring移植過來的IOC容器,Castle的IOC容器就是Windsor部分。它們均是輕量級的框架,比較成熟,其中Spring.Net已經被逐漸應用於各種項目中。

使用IOC框架應該註意什麼   

使用IOC框架產品能夠給我們的開發過程帶來很大的好處,但是也要充分認識引入IOC框架的缺點,做到心中有數,杜絕濫用框架。
    第一、軟體系統中由於引入了第三方IOC容器,生成對象的步驟變得有些複雜,本來是兩者之間的事情,又憑空多出一道手續,所以,我們在剛開始使用IOC框架的時候,會感覺系統變得不太直觀。所以,引入了一個全新的框架,就會增加團隊成員學習和認識的培訓成本,並且在以後的運行維護中,還得讓新加入者具備同樣的知識體系。
    第二、由於IOC容器生成對象是通過反射方式,在運行效率上有一定的損耗。如果你要追求運行效率的話,就必須對此進行權衡。
    第三、具體到IOC框架產品(比如:Spring)來講,需要進行大量的配製工作,比較繁瑣,對於一些小的項目而言,客觀上也可能加大一些工作成本。
    第四、IOC框架產品本身的成熟度需要進行評估,如果引入一個不成熟的IOC框架產品,那麼會影響到整個項目,所以這也是一個隱性的風險。
    我們大體可以得出這樣的結論:一些工作量不大的項目或者產品,不太適合使用IOC框架產品。另外,如果團隊成員的知識能力欠缺,對於IOC框架產品缺乏深入的理解,也不要貿然引入。最後,特別強調運行效率的項目或者產品,也不太適合引入IOC框架產品,象WEB2.0網站就是這種情況。

轉載:https://blog.csdn.net/wanghao72214/article/details/3969594


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

-Advertisement-
Play Games
更多相關文章
  • 一、要做成什麼樣 bs端的輪播控制項千千萬,有的甚至能作為一個單獨的庫來開發,所涉及到的功能也是繽紛多彩。相對來說,cs端的輪播用得不多,我這裡只是簡單的做了個能滿足一般需求的輪播,在項目中湊會湊會還是可以的。先給兩張圖,看看最後的效果: 如圖,整個結構就是左右箭頭、底部小點以及內同三大部分。雖然是簡 ...
  • 2018-08-24 c#金額轉換成中文大寫金額 decimal PriceSum = 32957.2654; 調用 var PriceSumChinese = MoneyToUpper(PriceSum.ToString()); 結果:叄萬貳仟玖佰伍拾柒圓貳角柒分 ...
  • 前言 List集合操作去除重覆數據的這種情況經常會碰到,博客園裡面也有很多大神們做過,在這裡主要是借鑒然後自己整理了一下,主要是為了方便自己,以後再次碰到這種去重問題,直接打開自己的鏈接拿起鍵盤就是乾,,,, 一、方法一 利用HashSet去重,在實體類里重寫Equals和GetHashCode方法 ...
  • 前言 前面講解了MEF的引用方法,介面的導入導出,類屬性的導入導出和集合的導出用法其實大家可以看到基本上大同小異的。 MEF的延遲載入 我們知道當裝配一個組件的時候,當前組件裡面的所有的Import的變數都自動去找到對應的Export而執行了實例化,有些時候出於程式效率的考慮,不需要立即實例化對象, ...
  • MEF導出類的方法和屬性 首先來說導出屬性,因為這個比較簡單,和導出類差不多,先來看看代碼,主要看我加註釋的地方,MusicBook.cs中的代碼如下: program.cs中的代碼如下: 下麵還用foreach遍歷輸出屬性的值,運行即可查看到結果。最後我會附上源碼供大家下載,這裡就不再截圖了。 下 ...
  • C 5.0 推出async和await,最早是.NET Framework 4.5引入,可以在Visual Studio 2012使用。在此之前的非同步編程實現難度較高,async使非同步編程的實現變得簡便。 各平臺對async的支持情況 |平臺|async| | | | |.NET 4.5及以上|& ...
  • 代碼: private static ImageCodecInfo GetImageCodecInfo(ImageFormat imageFormat) { ImageCodecInfo[] imageCodecInfoArr = ImageCodecInfo.GetImageDecoders(); ...
  • 前言 小編菜鳥級別的程式員最近感慨頗多,經歷了三五春秋深知程式路途遙遠而我滄海一粟看不到的盡頭到不了的終點何處是我停留的驛站。說了段廢話下麵進入正題吧! 什麼是MEF? MEF:全稱Managed Extensibility Framework(托管可擴展框架)。單從名字我們不難發現MEF是專門致力 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...