在面向對象的語言中,回調則是經過接口或抽象類來實現的,咱們把實現這種接口的類稱爲回調類,回調類的對象稱爲回調對象,其處理事件的方法叫作回調方法。(摘自百度百科)java
那麼經過上面那句話將百度百科中的「回調函數」翻譯成JAVA版:回調方法就是一個經過回調對象的引用(java中的引用存的是對象的地址)調用的方法。若是你把算法
回調對象的引用(地址)做參數傳遞給另外一個方法,當這個引用被用來調用其所指向的方法時,咱們就說這是回調方法。回調方法不是由該方法的實現方直接調用,
而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。設計模式
下面咱們來經過一個小需求來實現回調,需求爲:王鋼蛋去餐廳打飯,餐廳服務員根據其飯量爲其打飯。咱們先構思下,首先要有個接口,接口中定義個抽象方法爲 飯量(回調接口);其次建立王鋼蛋(回調類),讓王鋼蛋實現這個接口,並想好其飯量(回調方法);最後建立餐廳,餐廳服務員(另外一方)接待王鋼蛋(回調對 象)並根據其提供的飯量(回調方法)打飯(特定事件,該事件會調用回調方法)。上代碼:app
/** * 顧客,去食堂吃飯有個前提,要告訴服務員其飯量,纔會給你盛飯 * @author coder * */ interface Client{ /** * 告訴服務員其飯量 * @return */ public String appetite(); } class WangGangDan implements Client{ @Override public String appetite() { return "一車米飯"; } } /** *食堂 */ class Restaurant{ /** * 打飯方法,前提是客戶要告知服務員你的飯量,他會根據你的飯量給你「盛」飯 * @param client 排隊的客戶 * @return */ public String dozenRice(Client client){ return "盛了"+client.appetite(); } } public class Test1 { //業務處理類,老王去打飯 public static void main(String[] args) { WangGangDan laowang=new WangGangDan(); //王鋼蛋以別名laowang去食堂要飯 Restaurant waiter=new Restaurant(); String dozenRice=waiter.dozenRice(laowang); System.out.println(dozenRice); //最後老王「盛了一車米飯」 //可是一般咱們打飯時不會告訴服務員咱們叫什麼,這樣太麻煩了,那麼可不能夠只告訴服務員 //飯量多少就給咱們打飯呢?按常理來講咱們去餐廳也只會要一次飯。 //匿名內部類多用來實現回調,簡便 String dozenRice1=waiter.dozenRice(new Client(){ @Override public String appetite() { return "一鍋米飯"; }}); System.out.println(dozenRice1); } }
這裏將利用模板方法模式來講明鉤子方法是什麼,許多設計模式都用到了回調,鉤子之類的概念,這些基礎點理解了,有些模式也就不那麼晦澀難懂了,稍微改寫下上面的代碼就能夠:ide
/** * 模板方法模式:在一個方法中定義一個算法的骨架,而將一些步 * 驟延遲到子類中。模板方法使得子類能夠在不改變算法結構的情 * 況下,從新定義算法中的某些步驟。 * 【鉤子方法】:原理就是實現爲空的方法,在某任務以前、以後、 * 執行中、報異常後調用的方法(是否是有種熟悉的感受)。 * 一般鉤子方法是經過抽象類或是本類中的空方法來實現的。 * */ abstract class Client{ /** * 【模板方法】 */ public void templateMethod(){ before(); appetite(); after(); } /** * 【鉤子方法】在盛飯前(一個空的實現) */ protected void before(){}; /** * 【抽象方法】告訴服務員其飯量 * @return 飯量 */ public abstract void appetite(); /** * 【具體方法】盛飯後 */ private void after(){ //實際項目這裏是共有的業務邏輯 System.out.println("拿筷子,找桌子,開吃..."); } } /** *食堂 */ class Restaurant{ /** * 打飯方法,前提是客戶要告知服務員你的飯量,他會根據你的飯量給你「盛」飯 * @param client 排隊的客戶 * @return */ public void dozenRice(Client client){ client.templateMethod(); } } public class Test1 { //業務處理類,老王去打飯 public static void main(String[] args) { Restaurant waiter=new Restaurant(); waiter.dozenRice(new Client(){ @Override protected void before() { System.out.println("對服務員吹鬍子瞪眼!!"); } @Override public void appetite() { System.out.println("盛了一鍋米飯"); }}); } }