為什么寫Java程序需要接口
?
我之所以以這個作為標題,并不是為了玩噱頭,講一些似是而非的空話,還是以探索加發現,
追本溯源的講解一下為什么Java需要接口,怎么理解,怎么用它。
?
首先接口并不是Java才有的,這個是面向對象語言的基本特征之一。回想面向對象之前的那些
編程語言Win32 API中有個最經典的例子是當你在windows窗口中繪制一些內容以后,最大
化再最小化以后內容沒了,原因是你沒有捕獲重寫windows的一個WM_Paint的消息,
windows不知道你想繪制什么東西了,高人管這種應用叫CallBack(回調),意思是你調用
windows的paint方法繪制方法,但是windows不知道要繪制什么,結果回頭跟你要,你重
寫了它就繪出來,不然就什么都沒有一張白紙了。
?
然而當面向對象語言洶涌發展,各種設計模式應運大行其道,很少再有人提及Callback了,怎
么回事情,難道它消失了嗎,沒有它被面向對象語言換了個名字用得更加的大行其道,以致你以
為它不存在了,在Java中它就是接口。舉個Java中最簡單的例子,線程的Runnable接口,當
你在Java中啟動一個線程時候,Java通過調用thread.start()函數來幫你實現線程的啟動,但是
啟動以后它執行什么JVM并需要不知道,如果你不重寫run方法,就什么都不執行,原因在于
JVM并不知道你在線程里面想要干什么,而你又不能自己調度線程,線程調度依賴JVM本身實
現,所以這個是個很好的CallBack的例子,你調用start()方法讓JVM執行線程,JVM回調你實
現的線程run()方法。很完美的實現!沒有接口你怎么辦到。
?
另外個很好的例子,可以很完美的詮釋接口的秒用,Java編譯的時候常會有包依賴關系,假設A
要依賴B,這個沒問題,如果有一天你發現B中的類C居然要反過來訪問A里面的類D,你傻
眼了,這樣就會破壞AB之間的依賴關系,還會產生編譯錯誤,這個時候定義接口文件E在B中,
讓D繼承一下,傳回一個reference給C,問題很完美的解決,也許這么說比較復雜,看下圖:
?
就這樣,你還可以在D中調用C,想讓C執行D的方法process()只要回傳一個reference即可。
?
而Spring則將接口的概念更加的發揚光大,很多人接觸Spring就知道一個概念依賴注入,如果
定義個接口話,然后將引用配置在xml文件中,至于你需要的那個reference的接口幫你做什么
事情,完全由你自己決定,這是一個很偉大的思想,不過是把接口與實現更加測地的分離了,這
樣你再也不遇到因為包依賴關系導致的編譯錯誤,Spring的ApplicationContext與
XMLBeanFactory對象幫你自動實現了包依賴解耦。
?
最后你會發現,接口本質上不過在回調函數之上批了一件華麗的外衣,想當初WIN32 API的年
代,只有Callback這種東西真的滿天飛,而且現在還在飛!