1 ioc理論的背景
我們都知道在物件導向的應用中,軟體系統都是由n個物件組成的,它們通過彼此的合作,最終實現業務邏輯。
圖1:耦合在一起的物件
如果我們開啟機械式手錶的後蓋,就會看到與上面類似的情形,各個齒輪分別帶動時針、分針和秒針順時針旋轉,從而在表盤上產生正確的時間。上圖畫的就是這樣的乙個齒輪組,它擁有多個獨立的齒輪,這些齒輪相互嚙合在一起,協同工作,來共同完成某項任務。我們可以看到,在齒輪組中,如果有乙個齒輪出了問題,就可能會影響到整個齒輪組的運轉。
齒輪組中各個齒輪之間的嚙合關係,與軟體系統中物件與物件之間的耦合關係,非常類似。物件之間的耦合關係是必要的,是協同工作的基礎,當然也是無法避免的,否則無法保證系統整體的正常運轉。目前,很多任務業級的應用越來越龐大,物件之間的依賴關係也越來越複雜,就會出現物件之間的多重依賴性關係,因此,架構師和設計師對系統進行分析和設計將面臨很大的挑戰。物件之間耦合度過高的系統,必然會出現牽一髮而動全身的情形。
圖2:物件之間複雜的依賴關係
耦合關係不僅會出現在物件與物件之間,也會出現在軟體系統的各模組之間,以及軟體系統和硬體系統之間。如何降低系統之間、模組之間和物件之間的耦合度,是軟體工程永遠追求的目標之一。
所以有人就提出來ioc理論,用來實現物件之間的「解耦」,目前已被廣泛應用於很多專案中。
2 什麼是控制反轉(ioc)
ioc是inversion of control的縮寫,多數書籍翻譯成「控制反轉」,還有些書籍翻譯成為「控制反向」或者「控制倒置」,這些都大同小異,我個人覺得這個翻譯有待商榷,容易引起歧義,是不是翻譯為 「控制轉移」會更好一些。
2023年,michael mattson在一篇有關**物件導向框架的文章中,首先提出了ioc 這個概念。對於物件導向設計及程式設計的基本思想,前面我們已經講了很多了,不再贅述,讀者可以參考我前面的文章,簡單來說就是把複雜系統分解成相互合作的物件,這些物件類的內部實現是透明的,從而降低了解決問題的複雜度,而且可以靈活地被重用和擴充套件。ioc理論提出的觀點大體是這樣的:借助於「第三方」實現具有依賴關係的物件之間的解耦,如下圖:
圖3:ioc解耦示意圖
大家看到了吧,由於引進了中間的「第三方」,也就是ioc容器,使得a、b、c、d這4個物件沒有了耦合關係,齒輪之間的傳動全部依靠「第三方」了,所有物件的控制權全部上繳給「第三方」,這就是「控制反轉」說法的由來,意思就是各個物件的控制權都被轉移給「第三方」了。
從另乙個角度來看,作為「第三方」的ioc容器成了整個系統的關鍵核心,它起到了一種類似「粘合劑」的作用,把系統中的所有物件粘合在一起發揮作用,如果沒有這個「粘合劑」,物件與物件之間會彼此失去聯絡,這就是所謂的ioc容器被稱為「粘合劑」的原因。
我們再把上圖中間的ioc容器拿掉後,整個系統變為這樣的情形:
圖4:拿掉ioc容器後的系統
拿掉ioc容器後,我們看到的就是系統開發所需要完成的全部內容,這時候,a、b、c、d這4個物件之間已經沒有了耦合關係,彼此毫不影響,所以當你在實現class a的時候,根本不用再考慮b、c和d了,系統物件之間的依賴已經降低到了最低程度。至於ioc容器,你可以到開源組織的**上找一找,裡面有很多比較成熟而且free的,使用起來非常簡便。
如果真能實現控制反轉,對於系統開發而言,這將是一件多麼美好的事情!
3 什麼是依賴注入(di)
我們先看一些生活中的例子,幫助你理解依賴注入(di):
3.1 主機和內建硬碟
我們平時所用的電腦,它的硬碟安裝在主機裡面,從電腦的外部,我們是看不見硬碟的。所以,我們通常認為,電腦的所有部件是融為一體的。
圖5:主機和內建硬碟
對於一體機而言,一旦出現了問題,我們可能無法準確地判斷到底是什麼零部件出現了問題,有可能是cpu壞了,也有可能是主機板燒了,還有可能是記憶體鬆動了。還有的時候,比如,電腦硬碟出現了問題,可能導致整台電腦都無法使用。從這個例子,我們可以看到部件之間「緊密耦合」的產生的問題:無法準確的定位和診斷故障所在。這種情形,在軟體工程的理論中,稱之為可理解性和可測試性差。
如果你想修理電腦的硬碟,那麼在修理過程中就必須小心翼翼,不要把其它的部件再搞壞了,比如不慎把記憶體給碰鬆動了,硬碟固然是修好了,但整台電腦仍然無法使用。這種情形,在軟體工程的理論中,稱之為可修改性差。
可理解性、可測試性、可修改性組成了系統的可維護性,一體機的可維護性就表現得比較差。
3.2 主機和usb裝置
大家對usb介面和裝置應該都很熟悉。自從有了usb介面,給我們使用電腦帶來了很大的方便,現在有很多的外部裝置都支援usb介面。
圖6:主機和usb裝置
從軟體工程角度,我們分析一下usb帶來的好處:
1、usb裝置作為主機的外部裝置,在插入主機之前,與主機沒有任何的關係,兩者都可獨立進行測試,無論兩者中的任何一方出現什麼的問題,都不會影響另一方的執行,所以可維護性比較好。
2、同乙個usb裝置可以插接到不同的支援usb的任何主機,也就是usb裝置可以被重複利用,所以可復用性比較好。
3、支援熱插拔,只要是支援usb介面的裝置都可以接入,所以可擴充套件性比較好,非常靈活。
3.3 依賴注入
2023年,martin fowler從另乙個角度來思考這個問題,提出了「哪些方面的控制被反轉了?」這樣乙個問題,並給出了答案:「依賴物件的獲得被反轉」。於是,他給「控制反轉」取了乙個他認為更合適的名字叫做「依賴注入(dependency injection)」。他的這個答案,實際上點明了實現ioc理論的解決方法。所謂依賴注入,就是由ioc容器在執行期間,動態地將某種依賴關係注入到物件之中。
依賴注入(di)和控制反轉(ioc)是從不同的角度的描述的同一件事情,都是指通過引入第三方,即ioc容器,實現軟體系統中物件之間的解耦。
控制反轉能夠帶給系統開發的好處,與usb機制帶來的好處基本類似,而且依賴注入的實現跟usb機制也完全一樣。usb機制是現實中依賴注入的很好的案例。我們用乙個實際的例子,分析一下usb機制:
任務:主機通過usb介面讀取乙個檔案。
思路:首先,必須制定乙個usb介面標準,主機對usb裝置的訪問嚴格按照usb介面標準,usb裝置提供的功能也必須符合usb介面標準。
當主機需要獲取乙個檔案的時候,它直接去讀取usb介面,根本不會關心usb介面上連線的是什麼裝置。
如果我給主機連線上乙個u盤,那麼主機就從u盤上讀取檔案;如果我給主機連線上乙個外接硬碟,那麼主機就從外接硬碟上讀取檔案。選取何種外部裝置的權力由我說了算,也就是控制權歸我。
至此,依賴注入的思路已經非常清楚:當主機需要讀取檔案的時候,我就把它所要依賴的外部裝置,挑出來乙個,幫他掛接上。這個過程就是乙個被依賴的物件在系統執行時被注入另外乙個物件內部的過程。在這個過程中,我就起到了ioc容器的作用。
我們再把依賴注入應用到軟體工程中:
class a依賴於class b,當class a需要用到class b的時候,ioc容器就會立刻建立乙個class b送給class a使用。ioc容器就是乙個類製造工廠,你需要什麼,直接來拿,直接用就可以了,而不需要去關心你所用的東西是如何製成的,也不用關心最後是怎麼被銷毀的,這一切全由ioc容器包辦。
4 實現ioc容器
且看下文
**:
軟體構架師的特點
作為專案的技術主管,構架師的技術需要非常的廣泛,這比技術深度更加重要 當然構架師在特定的領域需要一定的技術深度 軟體構架師是技術主管 首先,軟體構架師是技術主管,這意味著除了他要有技術上的技能外,還要有很好的領導才能。構架師的領導能力在團隊中和專案質量控制中起著十分重要的作用。在團隊中,構架師是專案...
軟體構架師的特點
軟體構架師是技術主管 首先,軟體構架師是技術主管,這意味著除了他要有技術上的技能外,還要有很好的領導才能。構架師的領導能力在團隊中和專案質量控制中起著十分重要的作用。在團隊中,構架師是專案的技術總管,他需要有豐富的知識背景,以便作出技術上的決定。相對於構架師來說,專案經理是來管理專案的資源,時間進度...
軟體構架師的特點
軟體構架師是技術主管 架構師可能是有乙個小組來完成的 2首先,軟體構架師是技術主管,這意味著除了他要有技術上的技能外,還要有很好的領導才能。構架師的領導能力在團隊中和專案質量控制中起著十分重要的作用。在團隊中,構架師是專案的技術總管,他需要有豐富的知識背景,以便作出技術上的決定。相對於構架師來說,專...