控制反轉
此條目需要精通或熟悉計算機科學的編者參與及協助編輯。 |
控制反轉(英語:Inversion of Control,縮寫為IoC),是面向對象編程中的一種設計原則,可以用來減低計算機代碼之間的耦合度。其中最常見的方式叫做依賴注入(Dependency Injection,簡稱DI),還有一種方式叫「依賴查找」(Dependency Lookup)。
起源
早在2004年,Martin Fowler就提出了「哪些方面的控制被反轉了?」這個問題。他總結出是依賴對象的獲得被反轉了,因為大多數應用程序都是由兩個或是更多的類通過彼此的合作來實現業務邏輯,這使得每個對象都需要獲取與其合作的對象(也就是它所依賴的對象)的引用。如果這個獲取過程要靠自身實現,那麼這將導致代碼高度耦合並且難以維護和調試。
技術描述
Class A中用到了Class B的對象b,一般情況下,需要在A的代碼中顯式地用 new 建立 B 的對象。
採用依賴注入技術之後,A 的代碼只需要定義一個 private 的B對象,不需要直接 new 來獲得這個對象,而是通過相關的容器控制程序來將B對象在外部new出來並注入到A類里的引用中。而具體獲取的方法、對象被獲取時的狀態由配置文件(如XML)來指定。
IoC也可以理解為把流程的控制從應用程序轉移到框架之中。以前,應用程序掌握整個處理流程;現在,控制權轉移到了框架,框架利用一個引擎驅動整個流程的執行,框架會以相應的形式提供一系列的擴展點,應用程序則通過定義擴展的方式實現對流程某個環節的定製,「框架Call應用」。基於MVC的web應用程序就是如此。
實現方法
實現控制反轉主要有兩種方式:依賴注入和依賴查找。兩者的區別在於,前者是被動的接收對象,在類A的實例創建過程中即創建了依賴的B對象,通過類型或名稱來判斷將不同的對象注入到不同的屬性中,而後者是主動索取相應類型的對象,獲得依賴對象的時間也可以在代碼中自由控制。
依賴注入
依賴注入有如下實現方式:
- 基於接口。實現特定接口以供外部容器注入所依賴類型的對象。
- 基於 set 方法。實現特定屬性的public set方法,來讓外部容器調用傳入所依賴類型的對象。
- 基於構造函數。實現特定參數的構造函數,在新建對象時傳入所依賴類型的對象。
- 基於註解。基於Java的註解功能,在私有變量前加「@Autowired」等註解,不需要顯式的定義以上三種代碼,便可以讓外部容器傳入對應的對象。該方案相當於定義了public的set方法,但是因為沒有真正的set方法,從而不會為了實現依賴注入導致暴露了不該暴露的接口(因為set方法只想讓容器訪問來注入而並不希望其他依賴此類的對象訪問)。
依賴查找
依賴查找更加主動,在需要的時候通過調用框架提供的方法來獲取對象,獲取時需要提供相關的配置文件路徑、key等信息來確定獲取對象的狀態
控制反轉應用實例
C++
- PocoCapsule IoC and DSM framework (頁面存檔備份,存於網際網路檔案館) LGPL開源的,支持完全非侵入C++的控制反轉(IoC)及領域特定建模(DSM)容器
- hypodermic (頁面存檔備份,存於網際網路檔案館) MIT開源協議,Hypodermic是一個基於C++11開發的控制反轉(IoC)容器,它為你的C++對象協作提供依賴注入。Hypodermic靈感來自著名的.NET IoC項目Autofac。
Java
使用Java語言寫成的程式在控制反轉容器(Inversion of Control Container)裡應用了控制反轉(Martin 2004)。軟體需要一個來自容器的物件,而容器自行建構物件和它的附屬物。ATG 的 Dynamo 應用程式伺服器是第一個利用這途徑的環境之一,近來關於這些容器的例子包含了 HiveMind、PicoContainer (頁面存檔備份,存於網際網路檔案館)、Spring Framework(注意 Spring 是一個完整的企業平台,而非 IOC容器)、Apache Excalibur、Seasar 和 DPML Metro.
.NET
- Ninject (頁面存檔備份,存於網際網路檔案館)
- Spring.NET (頁面存檔備份,存於網際網路檔案館)
- ObjectBuilder (頁面存檔備份,存於網際網路檔案館)
- Structuremap (頁面存檔備份,存於網際網路檔案館)
- CastleProject
- Seasar (頁面存檔備份,存於網際網路檔案館)
- Autofac (頁面存檔備份,存於網際網路檔案館)
- Unity (頁面存檔備份,存於網際網路檔案館)
- MET
PHP
- Phalcon PHP框架中應用了依賴注入:DI in Phalcon (頁面存檔備份,存於網際網路檔案館)
- Laravel PHP框架核心的服務容器支持依賴注入:Service Container
參考文檔
- ^ Robert Cecil Martin. Agile Software Development: Principles, Patterns and Practices. Pearson Education. 2002. ISBN 978-0-13-597444-5.
- ^ Robert Cecil Martin. The Dependency Inversion Principle (PDF). [2005-11-15]. (原始內容 (PDF)存檔於2004-12-21).
- ^ Martin Fowler. Inversion of Control Containers and the Dependency Injection Pattern. 2004 [2005-11-15]. (原始內容存檔於2020-05-30).
- ^ Sony Mathew. Examining the Validity of Inversion of Control. 2005 [2005-11-16]. (原始內容存檔於2005-11-29).
- ^ Ke Jin. Domain Specific Modeling (DSM) in IoC frameworks. 2007 [2007-11-13]. (原始內容存檔於2007-11-15).
外部連結
- 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 (頁面存檔備份,存於網際網路檔案館)