java 回调(callback)函数简介.
一, 什么是回調(diào)函數(shù)(callback)
假如類(lèi)A有1個(gè)方法a(), 但是它不知道什么時(shí)候調(diào)用這個(gè)方法a().
而類(lèi)B告訴類(lèi)A, 我知道什么時(shí)候調(diào)用.??? 那么類(lèi)A就把自己交給類(lèi)B(作為類(lèi)B的一個(gè)成員),?? 當(dāng)時(shí)機(jī)適合時(shí), 類(lèi)B會(huì)調(diào)用類(lèi)A的a()方法.
那么a() 就叫回調(diào)(callback)方法.
可能我上面的解釋不夠好,
記住關(guān)鍵兩點(diǎn)就得了:
1. 類(lèi)A 要成為類(lèi)B的一個(gè)成員,??? java中是通過(guò)接口(interface)來(lái)實(shí)現(xiàn)的.
2. a()的執(zhí)行由類(lèi)B決定, 但是執(zhí)行的是類(lèi)A的方法a()
二, 什么要使用回調(diào)方法.
是啊, 為什么不直接使用類(lèi)A來(lái)調(diào)用a()呢?
實(shí)際上這個(gè)也涉及層次的問(wèn)題.
實(shí)際上, 類(lèi)B可以調(diào)用類(lèi)A的方法a(),?? 但是有時(shí)也可以調(diào)用其他比如類(lèi)c的方法c(), 只要類(lèi)c實(shí)現(xiàn)了接口, 替換成類(lèi)B的成員.
也就是說(shuō), 客戶(hù)端只需要跟類(lèi)B打交道, 無(wú)需知道實(shí)際執(zhí)行的哪個(gè)類(lèi)的哪個(gè)方法.
比如一個(gè)間公司有1個(gè)快遞部門(mén)(類(lèi)B), 所有員工都可以找這個(gè)快遞部門(mén)寄快遞,?? 但是實(shí)際上這個(gè)部門(mén)是用順豐(類(lèi)A)來(lái)快遞的.
但是當(dāng)順豐快遞有問(wèn)題時(shí),? 類(lèi)B也可以找另一間快遞公司,比如EMS(類(lèi)C)來(lái)實(shí)現(xiàn).
那么公司員工就不必與真正的快遞公司打交道, 只需把物件交給類(lèi)B去處理就ok了. 也就是這個(gè)過(guò)程是動(dòng)態(tài)的. 甚至也可以找另一件公司來(lái)實(shí)現(xiàn)(類(lèi)D), 只需要類(lèi)D實(shí)現(xiàn)快遞接口.
三, 基于上面快遞的一個(gè)具體例子
現(xiàn)在我們就基于上面的例子寫(xiě)一段代碼.
3.1 UML圖
可以見(jiàn)上面有5中角色
分別是:
員工:? Employee
快遞部門(mén): ExDepartment
回調(diào)(快遞)接口: Callbackable
具體快遞公司: SFExpress & EMS
下面是具體代碼:
3.2 Callbackable
這個(gè)接口只需要定義1個(gè)回調(diào)方法method()
public interface Callbackable {public void method(); }3.3 ExDepartment
同樣地, 快遞部門(mén)類(lèi)必須預(yù)留1個(gè)接口成員.
它可以選擇1個(gè)實(shí)現(xiàn)了Callbackable接口的對(duì)象作為自己的成員,
public class ExDepartment {private Callbackable exCompany;public void setExCompany(Callbackable exCompany) {this.exCompany = exCompany;}public ExDepartment(Callbackable exCompany){this.setExCompany(exCompany);}public void sendGoods(){exCompany.method();} }這個(gè)部門(mén)有1個(gè)快遞方法sendGoods(), 但是實(shí)際上是調(diào)用這個(gè)快遞公司成員的回調(diào)方法.method();
3.4 SFExpress
具體的快遞公司類(lèi)順豐, 必須實(shí)現(xiàn)Callbackable接口,
并重寫(xiě)里面回調(diào)方法.
3.5 EMS
同上
public class EMS implements Callbackable {public void EMSSendGoods(){System.out.println("Sent GOods by EMS");}@Overridepublic void method() {// TODO Auto-generated method stubthis.EMSSendGoods();}}3.6 Employee
員工類(lèi), 無(wú)需知道具體快遞公司的存在, 只需要跟快遞部門(mén)打交道就ok了
public class Employee {public void sendGoods(ExDepartment exd){exd.sendGoods();} }3.7 客戶(hù)端代碼和輸出:
ExDepartment exd = new ExDepartment(new SFExpress());Employee jack = new Employee();jack.sendGoods(exd);exd.setExCompany(new EMS());jack.sendGoods(exd);exd.setExCompany(new Callbackable() {@Overridepublic void method(){System.out.println("Sent goods by Jimmy!");}});jack.sendGoods(exd);輸出:
Sent goods by SF! Sent GOods by EMS Sent goods by Jimmy!可以見(jiàn)到, 員工寄了3次快遞, 第一次是順豐, 第一次是EMS, 但是第三次是某個(gè)人(可能兩個(gè)快遞公司都放假, 隨便找個(gè)人來(lái)送)
這個(gè)模型的好處時(shí),
無(wú)論有什么具體快遞類(lèi)的修改, 只需要修改快遞類(lèi)本身.
而增加快遞公司類(lèi), 只需讓那個(gè)類(lèi)實(shí)現(xiàn)回調(diào)接口, 而員工類(lèi)和快遞部門(mén)類(lèi)都無(wú)需修改的.
四, java的控件事件方法也是用回調(diào)來(lái)實(shí)現(xiàn)的.
上面的代碼有這么一段:
exd.setExCompany(new Callbackable() {@Overridepublic void method(){System.out.println("Sent goods by Jimmy!");}});上面用到了內(nèi)部類(lèi)的方法.
是不是覺(jué)得有d面善.
這種寫(xiě)法跟java的button事件定義優(yōu)點(diǎn)類(lèi)似.
下面是新建1個(gè)button的例子:
JButton btnNewButton = new JButton("New button");btnNewButton.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {}});其中btnNewButton就相當(dāng)于上面例子的快遞部門(mén)ExDepartment
而ActionListener實(shí)際上就是1個(gè)回調(diào)接口. (在這里也叫監(jiān)聽(tīng)器)
而actionPerFormed就是1個(gè)回調(diào)方法.
沒(méi)錯(cuò), java界面(awt/swt)的控件事件就是通過(guò)回調(diào)來(lái)實(shí)現(xiàn)的.
你們想想, 一個(gè)button,? 按下去做什么不是固定的.
有的button觸發(fā) 行為a(), 有些觸發(fā)行為b()
所以, 我們讓行為b()寫(xiě)成回調(diào)方法, 也就是所讓它所需的類(lèi)實(shí)現(xiàn) 回調(diào)接口ActionListener().
這樣, 就可以很靈活地為每1個(gè)button定義不同的觸發(fā)行為了!
總結(jié)
以上是生活随笔為你收集整理的java 回调(callback)函数简介.的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 为什么有人说面向对象编程就是面向接口编程
- 下一篇: Java 利用反射实现C#的委托