Java接口回調(diào)和方法回調(diào)的簡單實現(xiàn)步驟
先來聊接口回調(diào)
接口回調(diào)
這是一種設(shè)計模式,我的理解:
共有三者:調(diào)用者,被調(diào)用者和接口方法
接口回調(diào)的核心在于:調(diào)用者只需要實現(xiàn)接口方法,而被調(diào)用者只需要在合適的時機反過來調(diào)用調(diào)用者實現(xiàn)的方法,通過第三者接口方法,實現(xiàn)了雙向解耦,調(diào)用者不關(guān)心被調(diào)用者,被調(diào)用者不關(guān)心調(diào)用者如何實現(xiàn)方法的。
回調(diào)的核心思想是:
- 調(diào)用者(Caller) 提供一個實現(xiàn),交給 被調(diào)用者(Callee)。
- 被調(diào)用者在適當(dāng)?shù)臅r機,通過調(diào)用該實現(xiàn)來執(zhí)行相應(yīng)的邏輯。
"回調(diào)"的體現(xiàn)在于:正常都是調(diào)用者調(diào)用被調(diào)用者,而這里是被調(diào)用者主動調(diào)用調(diào)用者
接口回調(diào)的實現(xiàn)步驟
1. 定義接口
- 定義一個接口,其中包含需要被回調(diào)的方法。
2. 實現(xiàn)接口
- 由調(diào)用者(Caller)實現(xiàn)這個接口,并提供具體的回調(diào)邏輯。
3. 注冊接口
- 將實現(xiàn)接口的對象傳遞給被調(diào)用者(Callee)。
4. 在合適時機回調(diào)
- 被調(diào)用者在需要時調(diào)用接口中的方法,觸發(fā)回調(diào)邏輯。
舉例理解
舉一個生活中的例子,比如點外賣
這涉及到三者關(guān)系:
- app用戶(調(diào)用者)
- 餓了么app(被調(diào)用者)
- 聯(lián)系方式(接口方法實現(xiàn))
- 【用戶】填寫了聯(lián)系方式,比如地址和手機號(實現(xiàn)接口方法)
- 付款后,【餓了么】開始一系列操作(呼叫商家 ->呼叫騎手等)
- 無論如何,最終送餐的時候必須知道如何聯(lián)系【用戶】,會調(diào)用實現(xiàn)的接口方法
- 最終送到【用戶】手中
這個例子中,想想看,【用戶】作為調(diào)用者需要關(guān)心【餓了么】的一系列流程操作嗎?并不需要?!攫I了么】需要關(guān)心【用戶】的聯(lián)系方式嗎?呃。。。。好像的確挺關(guān)心的,這個例子翻車了?反正你能理解就行,聯(lián)系方式就算寫錯成其他戶的地址,【餓了么】的騎手也會照樣送過去,這么看也不算關(guān)心內(nèi)容了。
代碼案例
寫一個簡單的代碼案例,加深理解
public interface ButtonClickListener { void click(); // 回調(diào)方法 } public class Button { private ButtonClickListener listener; public void setButtonClickListener(ButtonClickListener listener){ this.listener = listener; } public void click(){ if (listener != null){ listener.click(); // 回調(diào)接口方法 } } } public class Main implements ButtonClickListener{ public static void main(String[] args) { // 創(chuàng)建被調(diào)用者實例 Button button = new Button(); // 創(chuàng)建調(diào)用者(Main)實例 Main main = new Main(); // 注冊回調(diào)接口 button.setButtonClickListener(main); // 模擬按鈕點擊 button.click(); } @Override public void click() { System.out.println("點擊按鈕"); } }
常見的接口回調(diào)
舉一個常用的Consumer接口經(jīng)常出現(xiàn)接口回調(diào)現(xiàn)象
關(guān)于Consumer接口可以看我另一篇博客:【Java】Java8的4個函數(shù)式接口簡單教程
Arrays.asList("a", "b", "c") .forEach(s -> System.out.println(s));
如上,這行代碼其實發(fā)生了隱式的接口回調(diào)
三者關(guān)系:
- 我(調(diào)用者):我調(diào)用了集合的forEach()方法,并且我實現(xiàn)了Consumer接口的抽象方法accept()
- forEach()(被調(diào)用者):forEach()方法會自動調(diào)用我實現(xiàn)的accept()方法
- Consumer.accept()(接口方法)
我只需要實現(xiàn)接口方法,forEach()會主動調(diào)用我實現(xiàn)的方法,并不關(guān)心我到底咋實現(xiàn)的
異步回調(diào)
上面說的都是同步回調(diào)
- 回調(diào)方法在調(diào)用的過程中立即被執(zhí)行。
- 示例:按鈕點擊監(jiān)聽。
異步回調(diào)是:
- 回調(diào)方法在調(diào)用結(jié)束后,異步地被執(zhí)行(通常是在另一個線程中)。
- 示例:網(wǎng)絡(luò)請求完成后通知調(diào)用者。
// 異步回調(diào)示例(模擬異步任務(wù)) public class AsyncTask { // 定義回調(diào)接口 public interface TaskCallback { void onTaskComplete(String result); } // 執(zhí)行異步任務(wù) public void execute(TaskCallback callback) { new Thread(() -> { try { Thread.sleep(2000); // 模擬耗時任務(wù) String result = "Task Finished!"; callback.onTaskComplete(result); // 回調(diào)通知任務(wù)完成 } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } } // 調(diào)用者代碼 public class Main { public static void main(String[] args) { AsyncTask task = new AsyncTask(); task.execute(result -> System.out.println("Callback received: " + result)); System.out.println("Task started..."); } }
注意事項
空指針檢查
- 如果沒有設(shè)置回調(diào)接口(即
listener
為null
),直接調(diào)用接口方法會拋出NullPointerException
。
if (listener != null) { listener.onClick(); }
線程安全
- 在多線程場景下,注意回調(diào)接口的線程安全問題,例如異步任務(wù)回調(diào)需要在主線程中執(zhí)行。
性能開銷
- 回調(diào)接口的調(diào)用會帶來一定的性能開銷,尤其是在高頻調(diào)用場景中,可能對性能產(chǎn)生影響。
強依賴問題
- 如果接口實現(xiàn)的方式過于復(fù)雜,會導(dǎo)致代碼難以維護,因此需要設(shè)計合理的接口和實現(xiàn)。
方法回調(diào)
差不多,看區(qū)別就行
核心記住一句話:將方法作為另一個方法的參數(shù)
方法回調(diào):
- 調(diào)用者將某個對象的方法引用直接傳遞給被調(diào)用者,被調(diào)用者在適當(dāng)時機調(diào)用這個方法。
- 不依賴接口,通常通過方法引用或 Lambda 表達(dá)式實現(xiàn)。
依賴接口 | 不需要接口,直接傳遞方法引用 | 需要接口,調(diào)用者實現(xiàn)接口并提供邏輯 |
靈活性 | 不靈活,直接綁定到具體類的方法 | 更靈活,支持不同實現(xiàn)類 |
解耦程度 | 較低,調(diào)用者和被調(diào)用者直接關(guān)聯(lián) | 高度解耦,通過接口隔離調(diào)用者與實現(xiàn)者 |
復(fù)雜性 | 簡單 | 相對復(fù)雜,但更適合擴展場景 |
- 方法回調(diào):簡單直接調(diào)用具體類的方法,適用于調(diào)用單一方法的場景。
- 接口回調(diào):強調(diào)解耦,適用于需要靈活多變的回調(diào)邏輯場景。
總結(jié)就行,區(qū)別不大,就是不用實現(xiàn)接口了
三者關(guān)系就變成,我調(diào)用forEach(),而forEach()調(diào)用了我寫的Caller.printMessage()方法
總結(jié)
到此這篇關(guān)于Java接口回調(diào)和方法回調(diào)的文章就介紹到這了,更多相關(guān)Java接口回調(diào)和方法回調(diào)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Web監(jiān)聽器Listener接口原理及用法實例
這篇文章主要介紹了Java Web監(jiān)聽器Listener接口原理及用法實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06