天天看點

Inversion of control

Inversion of control

From Wikipedia, the free encyclopedia

Jump to navigationJump to search

In ​​software engineering​​, inversion of control (IoC) is a programming principle. IoC inverts the ​​flow of control​​ as compared to traditional control flow. In IoC, custom-written portions of a ​​computer program​​ receive the flow of control from a generic ​​framework​​. A ​​software architecture​​ with this design inverts control as compared to traditional ​​procedural programming​​: in traditional programming, the custom code that expresses the purpose of the program ​​calls​​ into reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls into the custom, or task-specific, code.

Inversion of control is used to increase ​​modularity​​ of the program and make it ​​extensible​​,​​[1]​​ and has applications in ​​object-oriented programming​​ and other ​​programming paradigms​​. The term was used by Michael Mattsson in a thesis,​​[2]​​ taken from there​​[3]​​ by Stefano Mazzocchi and popularized by him in 1999 in a defunct Apache Software Foundation project, ​​Avalon​​, then further popularized in 2004 by ​​Robert C. Martin​​ and ​​Martin Fowler​​.

The term is related to, but different from, the ​​dependency inversion principle​​, which concerns itself with ​​decoupling dependencies​​ between ​​high-level and low-level​​ ​​layers​​ through shared ​​abstractions​​. The general concept is also related to ​​event-driven programming​​ in that it is often implemented using IoC so that the custom code is commonly only concerned with the handling of events, whereas the ​​event loop​​ and dispatch of events/messages is handled by the framework or the runtime environment.

​​1Overview​​

​​2Background​​

​​3Description​​

​​4Implementation techniques​​

​​5Examples​​

​​6See also​​

​​7References​​

​​8External links​​

As an example, with traditional programming, the ​​main function​​ of an application might make function calls into a menu library to display a list of available ​​commands​​ and query the user to select one.​​[4]​​ The library thus would return the chosen option as the value of the function call, and the main function uses this value to execute the associated command. This style was common in ​​text based interfaces​​. For example, an ​​email client​​ may show a screen with commands to load new mail, answer the current mail, start a new mail, etc., and the program execution would block until the user presses a key to select a command.

With inversion of control, on the other hand, the program would be written using a ​​software framework​​ that knows common behavioral and graphical elements, such as ​​windowing systems​​, menus, controlling the mouse, and so on. The custom code "fills in the blanks" for the framework, such as supplying a table of menu items and registering a code subroutine for each item, but it is the framework that monitors the user's actions and invokes the subroutine when a menu item is selected. In the mail client example, the framework could follow both the keyboard and mouse inputs and call the command invoked by the user by either means, and at the same time monitor the ​​network interface​​ to find out if new messages arrive and refresh the screen when some network activity is detected. The same framework could be used as the skeleton for a spreadsheet program or a text editor. Conversely, the framework knows nothing about Web browsers, spreadsheets or text editors; implementing their functionality takes custom code.

Inversion of control carries the strong connotation that the reusable code and the problem-specific code are developed independently even though they operate together in an application. ​​Callbacks​​, ​​schedulers​​, ​​event loops​​, ​​dependency injection​​, and the ​​template method​​ are examples of ​​design patterns​​ that follow the inversion of control principle, although the term is most commonly used in the context of ​​object-oriented programming​​.

Inversion of control serves the following design purposes:

To ​​decouple​​ the execution of a task from implementation.

To focus a module on the task it is designed for.

To free modules from assumptions about how other systems do what they do and instead rely on ​​contracts​​.

To prevent ​​side effects​​ when replacing a module.

Inversion of control is sometimes facetiously referred to as the "Hollywood Principle: Don't call us, we'll call you".

Inversion of control is not a new term in computer science. ​​Martin Fowler​​ traces the etymology of the phrase back to 1988,​​[5]​​ but it is closely related to the concept of program inversion described by ​​Michael Jackson​​ in his ​​Jackson Structured Programming​​ methodology in the 1970s.​​[6]​​ A ​​bottom-up parser​​ can be seen as an inversion of a ​​top-down parser​​: in the one case, the control lies with the parser, while in the other case, it lies with the receiving application.

​​Dependency injection​​ is a specific type of IoC.​​[4]​​ A ​​service locator​​ such as the ​​Java Naming and Directory Interface​​ (JNDI) is similar. In an article by Loek Bergman,​​[7]​​ it is presented as an architectural principle.

In an article by ​​Robert C. Martin​​,​​[8]​​ the dependency inversion principle and abstraction by layering come together. His reason to use the term "inversion" is in comparison with traditional software development methods. He describes the uncoupling of services by the abstraction of layers when he is talking about dependency inversion. The principle is used to find out where system borders are in the design of the abstraction layers.

In traditional programming, the ​​flow​​ of the ​​business logic​​ is determined by objects that are ​​statically bound​​ to one another. With inversion of control, the flow depends on the object graph that is built up during program execution. Such a dynamic flow is made possible by object interactions that are defined through abstractions. This ​​run-time binding​​ is achieved by mechanisms such as ​​dependency injection​​ or a ​​service locator​​. In IoC, the code could also be linked statically during compilation, but finding the code to execute by reading its description from ​​external configuration​​ instead of with a direct reference in the code itself.

In dependency injection, a dependent ​​object​​ or module is coupled to the object it needs at ​​run time​​. Which particular object will satisfy the dependency during program execution typically cannot be known at ​​compile time​​ using ​​static analysis​​. While described in terms of object interaction here, the principle can apply to other programming methodologies besides ​​object-oriented programming​​.

In order for the running program to bind objects to one another, the objects must possess compatible ​​interfaces​​. For example, class ​<code>​A​</code>​ may delegate behavior to interface ​<code>​I​</code>​ which is implemented by class ​<code>​B​</code>​; the program instantiates ​<code>​A​</code>​ and ​<code>​B​</code>​, and then injects ​<code>​B​</code>​ into ​<code>​A​</code>​.

In ​​object-oriented programming​​, there are several basic techniques to implement inversion of control. These are:

Using a ​​service locator pattern​​

Using ​​dependency injection​​, for example

Constructor injection

Parameter injection

Setter injection

Interface injection

Using a contextualized lookup

Using the ​​template method design pattern​​

Using the ​​strategy design pattern​​

In an original article by Martin Fowler,​​[9]​​ the first three different techniques are discussed. In a description about inversion of control types,​​[10]​​ the last one is mentioned. Often the contextualized lookup will be accomplished using a service locator

Most frameworks such as ​​.NET​​ or ​​Enterprise Java​​ display this pattern:

This basic outline in Java gives an example of code following the IoC methodology. It is important, however, that in the ​<code>​ServerFacade​</code>​ a lot of assumptions are made about the data returned by the ​​data access object​​ (DAO).

Although all these assumptions might be valid at some time, they couple the implementation of the ​<code>​ServerFacade​</code>​ to the DAO implementation. Designing the application in the manner of inversion of control would hand over the control completely to the DAO object. The code would then become

The example shows that the way the method ​<code>​respondToRequest​</code>​ is constructed determines if IoC is used. It is the way that parameters are used that define IoC. This resembles the ​​message-passing​​ style that some object-oriented programming languages use.

控制反轉

維基百科,自由的百科全書

跳轉到導航跳轉到搜尋

在軟體工程中,控制反轉 (IoC) 是一種程式設計原則。與傳統控制流相比,IoC 反轉了控制流。在 IoC 中,計算機程式的自定義編寫部分從通用架構接收控制流。與傳統的過程程式設計相比,具有這種設計的軟體架構颠倒了控制:在傳統程式設計中,表達程式目的的自定義代碼調用可重用的庫來處理通用任務,但在控制反轉時,它是架構調用自定義或特定于任務的代碼。

控制反轉用于增加程式的子產品化并使其可擴充,[1] 并在面向對象程式設計和其他程式設計範式中得到應用。該術語由 Michael Mattsson 在一篇論文中使用,[2] 取自 Stefano Mazzocchi 的論文 [3],并于 1999 年在一個已不複存在的 Apache 軟體基金會項目 Avalon 中推廣,然後在 2004 年由 Robert C. Martin 和馬丁福勒。

該術語與依賴倒置原則有關,但與依賴倒置原則不同,後者涉及通過共享抽象解耦高層和低層之間的依賴關系。一般概念也與事件驅動程式設計有關,因為它通常使用 IoC 實作,是以自定義代碼通常隻關注事件的處理,而事件循環和事件/消息的排程由架構或運作時環境。

内容

1 概述

2 背景

3 說明

4 實作技術

5個例子

6 另見

7 參考文獻

8 外部連結

概述

例如,在傳統程式設計中,應用程式的主要功能可能會将函數調用到菜單庫中,以顯示可用指令清單并詢問使用者選擇一個。[4]是以,庫将傳回所選選項作為函數調用的值,并且主函數使用該值來執行關聯的指令。這種風格在基于文本的界面中很常見。例如,電子郵件用戶端可能會顯示一個螢幕,其中包含加載新郵件、回複目前郵件、開始新郵件等指令,并且程式執行将一直阻塞,直到使用者按下某個鍵來選擇指令。

另一方面,通過控制反轉,程式将使用了解常見行為和圖形元素(例如視窗系統、菜單、控制滑鼠等)的軟體架構編寫。架構的自定義代碼“填空”,例如提供菜單項表并為每個項目注冊代碼子例程,但它是架構監視使用者的操作并在選擇菜單項時調用子例程.在郵件用戶端示例中,該架構可以同時跟蹤鍵盤和滑鼠輸入并通過任何一種方式調用使用者調用的指令,同時監視網絡接口以找出新消息是否到達并在某些時候重新整理螢幕。檢測到網絡活動。相同的架構可以用作電子表格程式或文本編輯器的架構。相反,該架構對 Web 浏覽器、電子表格或文本編輯器一無所知。實作它們的功能需要自定義代碼。

控制反轉具有很強的含義,即可重用代碼和特定于問題的代碼是獨立開發的,即使它們在應用程式中一起運作。回調、排程程式、事件循環、依賴注入和模闆方法是遵循控制反轉原則的設計模式的示例,盡管該術語最常用于面向對象程式設計的上下文中。

控制反轉用于以下設計目的:

将任務的執行與實作分離。

将子產品集中在其設計的任務上。

将子產品從關于其他系統如何做他們所做的假設中解放出來,而是依賴于契約。

防止更換子產品時産生副作用。

控制反轉有時被戲稱為“好萊塢原則:不要打電話給我們,我們會打電話給你”。

背景

控制反轉并不是計算機科學中的新術語。 Martin Fowler 将這個短語的詞源追溯到 1988 年,[5] 但它與邁克爾傑克遜在 1970 年代在他的傑克遜結構化程式設計方法中描述的程式反轉概念密切相關。 [6]自底向上解析器可以看作是自頂向下解析器的反轉:在一種情況下,控制權屬于解析器,而在另一種情況下,它屬于接收應用程式。

依賴注入是一種特定類型的 IoC。[4]服務定位器(例如 Java 命名和目錄接口 (JNDI))與此類似。在 Loek Bergman 的一篇文章中,[7] 它是作為一種架構原則提出的。

Robert C. Martin 的一篇文章[8] 将依賴倒置原理和分層抽象結合在一起。他使用“反轉”一詞的原因是與傳統的軟體開發方法進行比較。當他談論依賴倒置時,他通過層的抽象描述了服務的解耦。該原理用于找出抽象層設計中系統邊界的位置。

描述

在傳統程式設計中,業務邏輯的流向由互相靜态綁定的對象決定。通過控制反轉,流程取決于在程式執行期間建立的對象圖。通過抽象定義的對象互動使這種動态流成為可能。這種運作時綁定是通過依賴注入或服務定位器等機制實作的。在 IoC 中,代碼也可以在編譯期間靜态連結,但通過從外部配置讀取其描述而不是直接引用代碼本身來找到要執行的代碼。

在依賴注入中,依賴對象或子產品在運作時與它需要的對象耦合。在程式執行期間,哪個特定對象将滿足依賴性通常無法在編譯時使用靜态分析知道。雖然這裡是根據對象互動來描述的,但該原理可以應用于除面向對象程式設計之外的其他程式設計方法。

為了讓正在運作的程式将對象互相綁定,對象必須具有相容的接口。例如,類 A 可以将行為委托給由類 B 實作的接口 I;程式執行個體化 A 和 B,然後将 B 注入 A。

實作技術

在面向對象程式設計中,有幾種基本技術可以實作控制反轉。這些是:

使用服務定位器模式

使用依賴注入,例如

構造函數注入

參數注入

二傳手注入

接口注入

使用上下文查找

使用模闆方法設計模式

使用政策設計模式

在 Martin Fowler 的一篇原創文章中,[9] 讨論了前三種不同的技術。在關于控制類型反轉的描述中,[10] 提到了最後一個。通常上下文查找将使用服務定位器完成

例子

大多數架構(例如 .NET 或 Enterprise Java)都顯示這種模式:

公共類 ServerFacade {

public &lt;K, V&gt; V respondToRequest(K 請求) {

如果(businessLayer.validateRequest(請求)){

資料資料 = DAO.getData(request);

傳回 Aspect.convertData(data);

}

傳回空;

Java 中的這個基本大綱提供了一個遵循 IoC 方法的代碼示例。然而,重要的是,在 ServerFacade 中,對資料通路對象 (DAO) 傳回的資料做出了許多假設。

盡管所有這些假設在某些時候可能是有效的,但它們将 ServerFacade 的實作與 DAO 實作耦合。以控制反轉的方式設計應用程式會将控制權完全交給 DAO 對象。然後代碼會變成

public &lt;K, V&gt; V respondToRequest(K request, DAO dao) {

傳回 dao.getData(request);

該示例顯示方法 respondToRequest 的構造方式決定了是否使用 IoC。它是使用參數定義 IoC 的方式。這類似于某些面向對象的程式設計語言使用的消息傳遞風格。