淺談控制反轉,依賴註入與依賴查找

来源:http://www.cnblogs.com/maxstack/archive/2017/09/13/7516097.html
-Advertisement-
Play Games

今天要講的是以下三個概念: - 控制反轉 :IoC, Inversion of Control - 依賴註入:DI, Dependency Injection - 依賴查找:DL, Dependency Lookup, Service Locator 什麼是控制反轉 先說正常的控制流程是怎樣的: 比 ...


今天要講的是以下三個概念: - 控制反轉 :IoC, Inversion of Control - 依賴註入:DI, Dependency Injection - 依賴查找:DL, Dependency Lookup, Service Locator

 

什麼是控制反轉

先說正常的控制流程是怎樣的:       比如我寫了一個方法`process()`,在程式中的某處,我會自己調用這個方法,完成一些操作。如下示例:獲取了`input`參數,然後傳給`process()`進行處理。  
public static void main(String args[]) {
    Scanner sc = new Scanner(System. in);
    String input = sc.nextLine();
    process(input); // do something with the input
}

 

然後說反轉的控制流程是怎樣的:     這個`process`方法,我自己不會調用,而是把這件事交給某個模塊(Container/Framework)去調用,如下示例:用戶在TextField中輸入一些`input`,然後點擊Button來process。這個`process()`是綁定在Button的ActionListener上的,也就是說它運行的控制權交給了Swing框架,只有當Button被按下的時候,才會調用`process()`。  
public void prepareAndShowGUI() {
   JFrame mainFrame = new JFrame();
   JPanel controlPanel = new JPanel();
   JButton processButton = new JButton("Process");
   final JTextField inputText = new JTextField(10);
 
   processButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {     
         String input = inputText.getText();
         process(input); // do something with the input
      }
   });
 
   controlPanel.add(processButton);
   controlPanel.add(inputText);
   controlPanel.add(statusLabel);
   mainFrame.setSize(400, 100);
   mainFrame.add(controlPanel);
   mainFrame.addWindowListener(new WindowAdapter() {
       public void windowClosing(WindowEvent windowEvent){
          System.exit(0);
       }
    });
   mainFrame.setVisible(true);
}

 

有一個很有名的好萊塢原則和控制反轉的概念類似:Hollywood Principle - "Don't call us, we'll call you"。 

 

包,框架和容器 

先解釋包(library)和框架(framework),下兩段話摘錄自Martin Fowler的文章Inversion Of Control:  
A library is essentially a set of functions that you can call, these days usually organized into classes. Each call does some work and returns control to the client.   A framework embodies some abstract design, with more behavior built in. In order to use it you need to insert your behavior into various places in the framework either by subclassing or by plugging in your own classes. The framework's code then calls your code at these points.
  為了提高效率,代碼復用,我們寫的程式里會調用別人寫的包,這時我們的code就對別人的code有了依賴(dependency)。     為了更加提高效率,更加代碼復用,我們只寫和behavior有關的代碼,其它的事情都交給framework來做。     再解釋容器container的概念,在這裡可以認為是framework運行的環境,或者提供了對framework的實現。(註:這裡說的container和docker是兩個概念)   回到主題,我認為,控制反轉的出現,是對framework和container的一種理論支撐。我們已經習慣了包的調用,因為它很容易理解,其實就是調用方法,獲得返回值,這裡的控制流程是正向的,思維也是正向的。但是對框架的應用,剛上手往往很難理解,因為整個程式的控制流程由框架在掌握,思維需要轉個彎。    

房子,傢具和裝修

下麵我用一個比喻,來闡述包和框架的概念:   原始時期,寫程式就像搭小木屋,自己一根根木頭把房子造好,然後又一根根木頭打造桌子椅子,什麼事都親力親為,所有的功能都自己寫code實現。這個時候,我什麼外部的code都沒用。   慢慢地,我們發現可以用一些別人現成做好的東西,比如張三家產的石制桌椅,質量精良,比我自己做的木頭桌椅好多了,那我就拿過來用啊,自己只需要搭個屋子就好了,省了很多心力。這裡就用到了library。   再後來,乾這行的人多了,行業發展,自然產生了分工,有的人專門造房子,有的人專門做精裝修,有的人專門做傢具。我要造一間房子,傢具可以用別人生產的,房子可以用別人建好的毛坯房,自己只需要做做精裝修就好了,又省了不少力氣。   - 造房子相當於做framework/container - 做傢具相當於做library - 精裝修相當於寫業務邏輯   這裡的房子和傢具有一點特殊,做好了一個版本後就可以無限複製,但是精裝修的活每個客戶的需求都不一樣,需要大量勞動力,所以在這個行業里,一般大多數人都是做精裝修的,用了別人的房子,用了別人的傢具。   傢具因為裝修的時候處處能碰到,看的見摸得著,所以比較熟,但是房子這個東西,比較抽象,往往只知道卧室該放些什麼東西,廚房該放些什麼東西,但是卧室和廚房是怎麼連接起來的,包括房子中的各個部分是如何連接起來的,就不容易明白。

 

控制反轉的實現 

首先要問一個問題,為什麼要做控制反轉?我用包不行嗎?這個問題我思考了很久,最終我的想法是:實現業務邏輯,用包就夠了,即使用了某些框架,其實也不需要你去具體實現控制反轉。你只需要知道,這個框架做了什麼,我的業務邏輯在這個框架中寫在什麼位置就可以了,你不需要真的瞭解框架是怎樣實現的。可以把框架想象成一個黑盒,你只需要知道自己的應用放在黑盒的哪個位置就好了。     但是,如果要開發一個框架,就需要用到控制反轉,理解控制反轉,實現控制反轉。Martin講到了以下幾種實現方法,但是他同時也說,其實這些方法大同小異,原理都是一樣的(就是控制反轉啊)。   Single calls - closure: whenever the event is triggered, the program calls the closure binded to the event - have the framework define events and have the client code subscribe to these events   Multiple calls - framework: define an interface that a client code must implement for the relevant calls - template method: the super-class defines the flow of control, subclasses extend this overriding methods or implementing abstract methods to do the extension   看了之後一臉懵逼,那就舉個例子吧。   例: Closure   把閉包和控制反轉放到一起比較,兩者有類似的地方。之前說過,傳統的控制邏輯是,我調用某個方法/包來實現某個功能(比如log),或者處理數據得到一些返回值。因為Java函數設計的時候原則就是給定一些輸入值,得到一些輸出值,或者沒有返回值。與之不同的反轉控制邏輯是,我告訴你要乾一些什麼事情(輸入),我該幹嘛幹嘛,然後你覺得時機合適的時候再來叫我。這個不就是閉包把函數當成一個參數傳來傳去嗎?  
// calling service method
services.countGithubLikes(function(data) {
  // how to process the data after callback ...
});
 
// service method
countGithubLikes: function(callback) {
  // counting ...
  callback(); // calling callback to process data

 

鏈接

- Martin Flowler - Inversion Of Control - Martin Flowler - Service Locator vs Dependency Injection - JavaEE中的依賴性--依賴查找 - JavaEE中的依賴性--依賴性註入 - 控制反轉IOC之實現--依賴註入--依賴查找+依賴拖拽 - 依賴註入原理
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • package com.swift; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja... ...
  • 承接【Spring事務管理】,上一篇我們已經簡單接觸了關於Spring jdbc的知識,今天我們承接上一篇進行一下補充,上一篇直接將dataSource註入到了Dao層進行了實現,本篇我們通過簡單進行一下補充,將另外兩種實現為大家進行一下演示:1、在自己定義的DAO 實現類中註入一個DataSour ...
  • Coloring Trees CodeForces - 711C 題意:有n個點,每個點有一個c值,如果為0表示它沒有被染色,否則表示它被染成了c值的顏色。顏色有1到m。把第i棵樹染成顏色j所需要的代價是p[i][j]。求最小的代價,使得將每棵樹都染色,且如果將連續的一串同色的樹視為一個集合,共有k ...
  • 對於Spring相信很多做web開發的小活動一定不陌生,Spring中我們經常談到的就是IOC和AOP,但是對於Spring的事務管理,相信大家一定也很感興趣,今天我們就探討一下Spring中的事務管理。 首先談一下事務使用的場景,我們能想到的最常見場景就是銀行轉賬,A給B轉賬,第一步扣除A中的賬戶 ...
  • AJAX開發 AJAX即“Asynchronous Javascript And XML”(非同步JavaScript和XML),是指一種創建互動式網頁應用的網頁開發技術。 AJAX = 非同步 JavaScript和XML(標準通用標記語言的子集)。 AJAX 是一種用於創建快速動態網頁的技術。 通過 ...
  • 壞味道意指代碼中出現的可以被改進的地方。當你嗅到壞味道的時候,也就意味著重構的時機到了。 重構對軟體內部結構的一種調整,目的是在不改變軟體可觀察行為的前提下,提高其可理解性,降低其修改成本。 ...
  • 本期我們組的技術分享,打算跟大家講講服務治理。我在上篇文章中介紹了我們美團.點評北京總部用的OCTO框架,其實在上海點評部門用的是另一套Pigeon。這兩套框架都很重。這是和我們的業務有關的,其實服務治理這個東西都創業公司到成熟的大公司都在用,只是做到的程度不同。 先說說服務治理的邊界。本質上任何能 ...
  • 建造者模式是最後一個創建型設計模式,也是研究對象的創建。 將一個複雜對象的創建與它的表示分離,使得同樣的構建過程可以創建不同的表示。 創建和表示是什麼意思 ? 表示就是外在,對象具體的樣子,而內部構建過程是一種組裝的概念,有點像套娃,同樣的結構,但是卻產生了不同大小的樣子。 按照慣例,先講故事。 假 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...