依賴注入(DI) 控制反轉(IOC) 反射(Reflection) 面向切面編程AOP

一、依賴注入(DI) 控制反轉(IOC)
QQ截圖20160810142759.png
QQ截圖20160810143011.png
QQ截圖20160810143033.png

先看上面三張圖使用的公共組件ToggleBar,這個組件要求左按鈕和右按鈕點擊的時候,顯示的內容會向左或向右緩動,隱藏掉一部分,并顯示之前遮住的一部分。如圖所示,不同的應用場景,每一個小格子內容是不同的,有的是一個按鈕,有的是一個物品圖標,有的復雜些,還有文本,我們簡稱為renderA,renderB,renderC。這些變化的部分,作為ToggleBar的設計者,是不可預知的,可知的只有點擊左右按鈕,它們會排成一行做緩動。那么,我們應該怎么設計才能方便使用者呢?
毫無疑問,ToggleBar中必須有一個對象保存著這些變化的內容用來展示,就叫render吧。它的類型可以是renderA,renderB,renderC的基類,當然是一個接口更方便,把它們共有的邏輯再抽象到基類里。這樣ToggleBar就要求使用它的時候,必須指明一個render接口的對象,否則它不知道怎么去顯示。
第二個問題就是怎么把這個Render傳進去,最好是在構造方法里要求傳入,因為構造方法里需要執行UI初始化。也可以使用setRender方法重置。
總結:ToggleBar依賴render才能正常工作,但render的構造卻不受它控制,它把控制權交給了具體的使用者,這就是控制反轉。render通過構造方法傳入,這個就叫依賴注入。

以下參考輕松理解 Java開發中的依賴注入(DI)和控制反轉(IOC)

對比以下的兩個簡單程序:
簡單java程序
<pre>
package demo;
public class Activity {
public Activity(){
this.onCreate();
}
public void onCreate(){
System.out.println("onCreate called");
}
public void sayHi(){
System.out.println("Hello world!");
}
public static void main(String[] args) {
Activity a = new Activity();
a.sayHi();
}
}
</pre>

簡單Android程序
<pre>
package demo;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.append("Hello ");
tv.append("world!");
setContentView(tv);
}
}
</pre>

這兩個程序最大的區別就是,前者程序的運行完全由開發控制,后者程序的運行由Android框架控制.兩個程序都有個onCreate方法.前者程序中,如果開發者覺得onCreate 名稱不合適,想改為Init,沒問題,直接就可以改, 相比下,后者的onCreate 名稱就不能修改.因為,后者使用了框架,享受框架帶來福利的同時,就要遵循框架的規則.
這就是控制反轉.可以說, 控制反轉是所有框架最基本的特征.也是框架和普通類庫最大的不同點.
很多Android開發工程師在享用控制反轉帶來的便利,去不知什么是控制反轉.就有點像深海里的魚不知到什么是海水一樣.
通過框架可以把許多共用的邏輯放到框架里,讓用戶專注自己程序的邏輯.這也是為什么現在,無論手機開發,網頁開發,還是桌面程序, 也不管是Java,PHP,還是Python框架無處不在.

二、反射

通過字符串獲取類,動態生成對象。可以使用XML文件來組織這些字符串。反射主要是升級了工廠模式。
參考
Java反射入門
Java基礎與提高干貨系列——Java反射機制

以下參考Java反射機制的適用場景及其利與弊

  • Java的反射機制在做基礎框架的時候非常有用,有一句話這么說來著:反射機制是很多Java框架的基石。而一般應用層面很少用,不過這種東西,現在很多開源框架基本都已經給你封裝好了,自己基本用不著寫。典型的除了hibernate之外,還有spring也用到很多反射機制。經典的就是在xml文件或者properties里面寫好了配置,然后在Java類里面解析xml或properties里面的內容,得到一個字符串,然后用反射機制,根據這個字符串獲得某個類的Class實例,這樣就可以動態配置一些東西,不用每一次都要在代碼里面去new或者做其他的事情,以后要改的話直接改配置文件,代碼維護起來就很方便了,同時有時候要適應某些需求,Java類里面不一定能直接調用另外的方法,這時候也可以通過反射機制來實現。
    總的來說,自己寫的很少,具體什么時候要用那要看需求,反射機制無非就是根據一個String來得到你要的實體對象,然后調用它原來的東西。但是如果是要自己寫框架的話,那就會用得比較多了。
  • 當你做一個軟件可以安裝插件的功能,你連插件的類型名稱都不知道,你怎么實例化這個對象呢?因為程序是支持插件的(第三方的),在開發的時候并不知道 。所以無法在代碼中 New出來 ,但反射可以,通過反射,動態加載程序集,然后讀出類,檢查標記之后再實例化對象,就可以獲得正確的類實例。
  • 在編碼階段不知道那個類名,要在運行期從配置文件讀取類名, 這時候就沒有辦法硬編碼new ClassName(),而必須用到反射才能創建這個對象.反射的目的就是為了擴展未知的應用。比如你寫了一個程序,這個程序定義了一些接口,只要實現了這些接口的dll都可以作為插件來插入到這個程序中。那么怎么實現呢?就可以通過反射來實現。就是把dll加載進內存,然后通過反射的方式來調用dll中的方法。很多工廠模式就是使用的反射。
三、AOP

參考JavaWeb過濾器.監聽器.攔截器-原理&區別-個人總結
面向切面編程(AOP是Aspect Oriented Program的首字母縮寫) ,我們知道,面向對象的特點是繼承、多態和封裝。而封裝就要求將功能分散到不同的對象中去,這在軟件設計中往往稱為職責分配。實際上也就是說,讓不同的類設計不同的方法。這樣代碼就分散到一個個的類中去了。這樣做的好處是降低了代碼的復雜程度,使類可重用。但是人們也發現,在分散代碼的同時,也增加了代碼的重復性。什么意思呢?比如說,我們在兩個類中,可能都需要在每個方法中做日志。按面向對象的設計方法,我們就必須在兩個類的方法中都加入日志的內容。也許他們是完全相同的,但就是因為面向對象的設計讓類與類之間無法聯系,而不能將這些重復的代碼統一起來。也許有人會說,那好辦啊,我們可以將這段代碼寫在一個獨立的類獨立的方法里,然后再在這兩個類中調用。但是,這樣一來,這兩個類跟我們上面提到的獨立的類就有耦合了,它的改變會影響這兩個類。那么,有沒有什么辦法,能讓我們在需要的時候,隨意地加入代碼呢?**這種在運行時,動態地將代碼切入到類的指定方法、指定位置上的編程思想就是面向切面的編程。 **一般而言,我們管切入到指定類指定方法的代碼片段稱為切面,而切入到哪些類、哪些方法則叫切入點。有了AOP,我們就可以把幾個類共有的代碼,抽取到一個切片中,等到需要時再切入對象中去,從而改變其原有的行為。這樣看來,AOP其實只是OOP的補充而已。OOP從橫向上區分出一個個的類來,而AOP則從縱向上向對象中加入特定的代碼。有了AOP,OOP變得立體了。如果加上時間維度,AOP使OOP由原來的二維變為三維了,由平面變成立體了。從技術上來說,AOP基本上是通過代理機制實現的。AOP在編程歷史上可以說是里程碑式的,對OOP編程是一種十分有益的補充。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,287評論 25 708
  • 團隊開發框架實戰—面向切面的編程 AOP 引言 軟件開發的目標是要對世界的部分元素或者信息流建立模型,實現軟件系統...
    Bobby0322閱讀 4,176評論 4 49
  • 蟋蟀聒噪著 天漸漸黑的早了 夏日的余溫 被秋風吹散 換來梧桐樹葉 散落滿地 針織衫和碎花裙 遠處傳來的狗吠 雨滴淅...
    Sarah_Genia閱讀 112評論 0 0
  • 01 今天早上醒來的時候在公眾號的后臺收到了一個土豆發來的消息:每天到十點就一直會點開看看,等待你的推文或圖片,今...
    potatohorse閱讀 522評論 6 1