控制反轉
控制反轉(Inversion of Control,縮寫為IoC),是物件導向程式設計中的一種設計原則,可以用來減低電腦代碼之間的耦合度。其中最常見的方式叫做依賴注入(Dependency Injection,簡稱DI),還有一種方式叫「依賴尋找」(Dependency Lookup)。通過控制反轉,對象在被建立的時候,由一個調控系統內所有對象的外界實體,將其所依賴的對象的參照傳遞給它。也可以說,依賴被注入到對象中。
起源
早在2004年,Martin Fowler就提出了「哪些方面的控制被反轉了?」這個問題。他總結出是依賴對象的獲得被反轉了,因為大多數應用程式都是由兩個或是更多的類通過彼此的合作來實現業務邏輯,這使得每個對象都需要與其合作的對象(也就是它所依賴的對象)的參照。如果這個取得過程要靠自身實現,那麼這將導致代碼高度耦合並且難以維護和除錯。
技術描述
Class A中用到了Class B的對象b,一般情況下,需要在A的代碼中顯式的new一個B的對象。
採用依賴注入技術之後,A的代碼只需要定義一個私有的B對象,不需要直接new來獲得這個對象,而是通過相關的容器控制程式來將B對象在外部new出來並注入到A類里的參照中。而具體取得的方法、對象被取得時的狀態由設定檔(如XML)來指定。
實現方法
實現控制反轉主要有兩種方式:依賴注入和依賴尋找。兩者的區別在於,前者是被動的接收對象,在類A的實例建立過程中即建立了依賴的B對象,通過類型或名稱來判斷將不同的對象注入到不同的數屬性中,而後者是主動索取回應名稱的對象,獲得依賴對象的時間也可以在代碼中自由控制。
依賴注入
依賴注入有如下實現方式:
- 基於介面。實現特定介面以供外部容器注入所依值型別的對象。
- 基於 set 方法。實現特定屬性的public set方法,來讓外部容器呼叫傳入所依值型別的對象。
- 基於建構函式。實現特定參數的建構函式,在新建對象時傳入所依值型別的對象。
- 基於註解。基於Java的註解功能,在私有變數前加「@Autowired」等註解,不需要顯式的定義以上三種代碼,便可以讓外部容器傳入對應的對象。該方案相當於定義了public的set方法,但是因為沒有真正的set方法,從而不會為了實現依賴注入導致暴露了不該暴露的介面(因為set方法只想讓容器訪問來注入而並不希望其他依賴此類的對象訪問)。
依賴尋找
依賴尋找更加主動,在需要的時候通過呼叫框架提供的方法來取得對象,取得時需要提供相關的設定檔路徑、key等資訊來確定取得對象的狀態
控制反轉應用實例
C++
- PocoCapsule IoC and DSM framework GPL開源的,支援完全非侵入C++的控制反轉(IoC)及領域特定建模(DSM)容器
Java
使用Java語言寫成的程式在控制反轉容器(Inversion of Control Container)裡應用了控制反轉(Martin 2004)。軟體需要一個來自容器的物件,而容器自行建構物件和它的附屬物。ATG 的 Dynamo 應用程式伺服器是第一個利用這途徑的環境之一,近來關於這些容器的例子包含了 HiveMind、PicoContainer、Spring Framework(注意 Spring 是一個完整的企業平台,而非 IOC容器)、Apache Excalibur、Seasar 和 DPML Metro.
.NET
參考文件
- ^ Robert Cecil Martin. Agile Software Development: Principles, Patterns and Practices. Pearson Education. 2002. ISBN 0-13-597444-5.
- ^ Robert Cecil Martin. The Dependency Inversion Principle (PDF). [2005-11-15].
- ^ Martin Fowler. Inversion of Control Containers and the Dependency Injection Pattern. 2004 [2005-11-15].
- ^ Sony Mathew. Examining the Validity of Inversion of Control. 2005 [2005-11-16].
- ^ Ke Jin. Domain Specific Modeling (DSM) in IoC frameworks. 2007 [2007-11-13].
外部連接
- Another description of IOC
- A list of "Open Source Inversion of Control Containers"
- A simple demo of Inversion of Control (using Spring framework)
- Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler
- Needle, a dependency injection (inversion of control) container for Ruby
- Drip IoC, a dependency injection (inversion of control) container for PHP4
- PyContainer, a dependency injection (inversion of control) container for Python
- Qt Ioc Container, a dependency injection (inversion of control) container for C++
- Introducing Castle, explains the problems that Inversion of control containers try to solve (using Castle Project)
- PocoCapsule An open source IoC and DSM framework for C++
- Domain Specific Modeling (DSM) in IoC frameworks