Java 回撥機制(CallBack) 趣解
序言
最近學習java,接觸到了回撥機制(CallBack)。初識時感覺比較混亂,而且在網上搜尋到的相關的講解,要麼一言帶過,要麼說的比較單純的像是給CallBack做了一個定義。當然了,我在理解了回撥之後,再去看網上的各種講解,確實沒什麼問題。但是,對於初學的我來說,缺了一個循序漸進的過程。此處,將我對回撥機制的個人理解,按照由淺到深的順序描述一下,如有不妥之處,望不吝賜教!
開始之前,先想象一個場景:幼稚園的小朋友剛剛學習了10以內的加法。
第1章. 故事的緣起
幼師在黑板上寫一個式子 “1 + 1 = ”,由小明同學來填空。
由於已經學習了10以內的加法,小明同學可以完全靠自己來計算這個題目,模擬該過程的程式碼如下:
public class Student { private String name = null; public Student(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } private int calcADD(int a, int b) { return a + b; } public void fillBlank(int a, int b) { int result = calcADD(a, b); System.out.println(name + "心算:" + a + " + " + b + " = " + result); } }
public class Test { public static void main(String[] args) { int a = 1; int b = 1; Student s = new Student("小明"); s.fillBlank(a, b); } }
小明心算:1 + 1 = 2
該過程完全由Student類的例項物件單獨完成,並未涉及回撥機制。
第2章. 幼師的找茬
課間,幼師突發奇想在黑板上寫了“168 + 291 = ”讓小明完成,然後回辦公室了。
花擦!為什麼所有老師都跟小明過不去啊?明明超綱了好不好!這時候小明同學明顯不能再像上面那樣靠心算來完成了,正在懵逼的時候,班上的小紅同學遞過來一個只能計算加法的計算器(奸商啊)!!!!而小明同學恰好知道怎麼用計算器,於是通過計算器計算得到結果並完成了填空。
計算器的程式碼為:
public class Calculator { public int add(int a, int b) { return a + b; } }
public class Student { private String name = null; public Student(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } @SuppressWarnings("unused") private int calcADD(int a, int b) { return a + b; } private int useCalculator(int a, int b) { return new Calculator().add(a, b); } public void fillBlank(int a, int b) { int result = useCalculator(a, b); System.out.println(name + "使用計算器:" + a + " + " + b + " = " + result); } }
public class Test { public static void main(String[] args) { int a = 168; int b = 291; Student s = new Student("小明"); s.fillBlank(a, b); } }
小明使用計算器:168 + 291 = 459
該過程中仍未涉及到回撥機制,但是部分小明的部分工作已經實現了轉移,由計算器來協助實現。
3. 幼師回來了
發現小明完成了3位數的加法,老師覺得小明很聰明,是個可塑之才。於是又在黑板上寫下了“26549 + 16487 = ”,讓小明上課之前完成填空,然後又回辦公室了。
小明看著教室外面撒歡兒的小夥伴,不禁悲從中來。再不出去玩,這個課間就要廢了啊!!!! 看著小紅再一次遞上來的計算器,小明心生一計:讓小紅代勞。
小明告訴小紅題目是“26549 + 16487 = ”,然後指出填寫結果的具體位置,然後就出去快樂的玩耍了。
這裡,不把小紅單獨實現出來,而是把這個只能算加法的計算器和小紅看成一個整體,一個會算結果還會填空的超級計算器。這個超級計算器需要傳的引數是兩個加數和要填空的位置,而這些內容需要小明提前告知,也就是小明要把自己的一部分方法暴漏給小紅,最簡單的方法就是把自己的引用和兩個加數一塊告訴小紅。
因此,超級計算器的add方法應該包含兩個運算元和小明自身的引用,程式碼如下:
public class SuperCalculator { public void add(int a, int b, Student xiaoming) { int result = a + b; xiaoming.fillBlank(a, b, result); } }
public class Student { private String name = null; public Student(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } public void callHelp (int a, int b) { new SuperCalculator().add(a, b, this); } public void fillBlank(int a, int b, int result) { System.out.println(name + "求助小紅計算:" + a + " + " + b + " = " + result); } }
public class Test { public static void main(String[] args) { int a = 26549; int b = 16487; Student s = new Student("小明"); s.callHelp(a, b); } }
小明求助小紅計算:26549 + 16487 = 43036
執行流程為:小明通過自身的callHelp方法呼叫了小紅(new SuperCalculator())的add方法,在呼叫的時候將自身的引用(this)當做引數一併傳入,小紅在使用計算器得出結果之後,回撥了小明的fillBlank方法,將結果填在了黑板上的空格里。
燈燈燈!到這裡,回撥功能就正式登場了,小明的fillBlank方法就是我們常說的回撥函式。
通過這種方式,可以很明顯的看出,對於完成老師的填空題這個任務上,小明已經不需要等待到加法做完且結果填寫在黑板上才能去跟小夥伴們撒歡了,填空這個工作由超級計算器小紅來做了。回撥的優勢已經開始體現了。
第4章. 門口的婆婆
幼稚園的門口有一個頭發花白的老婆婆,每天風雨無阻在那裡擺著地攤賣一些快過期的垃圾食品。由於年紀大了,腦子有些糊塗,經常算不清楚自己掙了多少錢。有一天,她無意間聽到了小明跟小夥伴們吹噓自己如何在小紅的幫助下與幼師鬥智鬥勇。於是,婆婆決定找到小紅牌超級計算器來做自己的小幫手,並提供一包衛龍辣條作為報酬。小紅經不住誘惑,答應了。
回看一下上一章的程式碼,我們發現小紅牌超級計算器的add方法需要的引數是兩個整型變數和一個Student物件,但是老婆婆她不是學生,是個小商販啊,這裡肯定要做修改。這種情況下,我們很自然的會想到繼承和多型。如果讓小明這個學生和老婆婆這個小商販從一個父類進行繼承,那麼我們只需要給小紅牌超級計算器傳入一個父類的引用就可以啦。
不過,實際使用中,考慮到java的單繼承,以及不希望把自身太多東西暴漏給別人,這裡使用從介面繼承的方式配合內部類來做。
換句話說,小紅希望以後繼續向班裡的小朋友們提供計算服務,同時還能向老婆婆提供算賬服務,甚至以後能夠擴充其他人的業務,於是她向所有的顧客約定了一個辦法,用於統一的處理,也就是自己需要的運算元和做完計算之後應該怎麼做。這個統一的方法,小紅做成了一個介面,提供給了大家,程式碼如下:
public interface doJob { public void fillBlank(int a, int b, int result); }
因為靈感來自幫小明填空,因此小紅保留了初心,把所有業務都當做填空(fillBlank)來做。
同時,小紅修改了自己的計算器,使其可以同時處理不同的實現了doJob介面的人,程式碼如下:
public class SuperCalculator { public void add(int a, int b, doJob customer) { int result = a + b; customer.fillBlank(a, b, result); } }
小明的:
public class Student { private String name = null; public Student(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } public class doHomeWork implements doJob { @Override public void fillBlank(int a, int b, int result) { // TODO Auto-generated method stub System.out.println(name + "求助小紅計算:" + a + " + " + b + " = " + result); } } public void callHelp (int a, int b) { new SuperCalculator().add(a, b, new doHomeWork()); } }
public class Seller { private String name = null; public Seller(String name) { // TODO Auto-generated constructor stub this.name = name; } public void setName(String name) { this.name = name; } public class doHomeWork implements doJob { @Override public void fillBlank(int a, int b, int result) { // TODO Auto-generated method stub System.out.println(name + "求助小紅算賬:" + a + " + " + b + " = " + result + "元"); } } public void callHelp (int a, int b) { new SuperCalculator().add(a, b, new doHomeWork()); } }
public class Test { public static void main(String[] args) { int a = 56; int b = 31; int c = 26497; int d = 11256; Student s1 = new Student("小明"); Seller s2 = new Seller("老婆婆"); s1.callHelp(a, b); s2.callHelp(c, d); } }
小明求助小紅計算:56 + 31 = 87 老婆婆求助小紅算賬:26497 + 11256 = 37753元
最後的話
可以很明顯的看到,小紅已經把這件事情當做一個事業來做了,看她給介面命的名字doJob就知道了。
有人也許會問,為什麼老婆婆擺攤能掙那麼多錢? 你的關注點有問題好嗎!!這裡聊的是回撥機制啊!!
我只知道,後來小紅的業務不斷擴大,終於在幼稚園畢業之前,用掙到的錢買了人生的第一套房子。
相關文章
- Java回撥機制解讀Java
- Java——回撥機制Java
- Java介面回撥機制詳解Java
- js 回撥 callbackJS
- 回撥機制詳解
- java回撥函式機制Java函式
- 回撥函式(CallBack)函式
- 深入淺出Java回撥機制Java
- 初步講解JS中的callback回撥原理JS
- JS之回撥函式(callback)JS函式
- 深入淺出: Java回撥機制(非同步)Java非同步
- Java 非同步回撥機制例項解析Java非同步
- React Render Callback Pattern(渲染回撥模式)React模式
- JavaScript基礎——回撥(callback)是什麼JavaScript
- 函式指標&回撥函式Callback函式指標
- 關於Callback回撥,傳遞引數
- C++回撥函式(callback)的使用C++函式
- 關於 js 中的回撥函式 callbackJS函式
- 理解javascript中的回撥函式(callback)【轉】JavaScript函式
- java回撥函式-非同步回撥-簡明講解Java函式非同步
- 面試官:你知道Callback Hell(回撥地獄)嗎?面試
- 程式設計思想基本概念之回撥(Callback)程式設計
- 1.3 - Laravel 5.6 - Callbacks 回撥函式機制Laravel函式
- 夯實Java基礎系列11:深入理解Java中的回撥機制Java
- java介面回撥Java
- android下的callback機制Android
- iOS 如何優雅的處理“回撥地獄Callback hell”(一)iOS
- jni回撥java方法Java
- Java--回撥模型Java模型
- java回撥函式Java函式
- 一個Demo帶你理解Android介面回撥機制Android
- java 介面回撥經典案例--網路請求回撥Java
- java 回撥函式示例Java函式
- iOS如何優雅的處理“回撥地獄Callback hell”(二)——使用SwiftiOSSwift
- iOS如何優雅的處理“回撥地獄Callback hell”(一)——使用PromiseKitiOSPromise
- 當觀察者模式和回撥機制遇上Android原始碼模式Android原始碼
- C++中實現回撥機制的幾種方式[轉]C++
- Java回撥函式的理解Java函式