java回調機制
回調概念:
軟體模組之間總是存在著一定的介面,從調用方式上,可以把他們分為三類:同步調用、回調和非同步呼叫。同步調用是一種阻塞式調用,調用方要等待對方執行完畢才返回,它是一種單向調用;回調是一種雙向調用模式,也就是說,被呼叫者在介面被調用時也會調用對方的介面;非同步呼叫是一種類似訊息或事件的機制,不過它的調用方向剛好相反,介面的服務在收到某種訊息或發生某種事件時,會主動通知客戶方(即調用客戶方的介面)。回調和非同步呼叫的關係非常緊密,通常我們使用回調來實現非同步訊息的註冊,通過非同步呼叫來實現訊息的通知。同步調用是三者當中最簡單的,而回調又常常是非同步呼叫的基礎。java實現回調:
在 Java 支援方法指標之前,Java 介面不能提供一種實現回調的好方法。如果您習慣於傳遞在事件驅動編程模型中調用的函數指標,則您會喜歡本技巧。 熟悉 MS-Windows 和 X Window System 事件驅動編程模型的開發人員,習慣於傳遞在某種事件發生時調用(即“回調”)的函數指標。Java 的物件導向模型目前並不支援方法指標,這樣似乎就不可能使用這種很好的機制。但我們並不是一點辦法都沒有!
Java 的介面支援提供了一種獲得回調的等價功能的機制。其技巧就是:定義一個簡單介面,並在該介面中聲明我們要調用的方法。 例如,假定我們希望在某個事件發生時得到通知。我們可以定義一個介面: public interface InterestingEvent
{
// 這僅是一個常規方法。因此如果需要,
// 它可有傳回值,也可接收參數。
public void interestingEvent ();
}這使得我們可以控制實現該介面的類的任何對象。因此,我們不必關心任何外部類型資訊。與在將 C++ 代碼用於 Motif 時使用視窗小組件的資料域來容納對象指標的難以控制的 C 函數相比,這種方法要好得多。 發出事件訊號的類必須等待實現了 InterestingEvent 介面的對象,並在適當時候調用 interestingEvent() 方法。 public class EventNotifier
{
private InterestingEvent ie;
private boolean somethingHappened;public EventNotifier (InterestingEvent event)
{
// 儲存事件對象以備後用。
ie = event;
// 還沒有要報告的事件。
somethingHappened = false;
}
//... public void doWork ()
{
// 檢查在別處設定的謂詞。
if (somethingHappened)
{
// 通過調用介面的這個方法發出事件訊號。
ie.interestingEvent ();
}
//...
}// ...
}在上例中,我使用 somethingHappened 謂詞來跟蹤是否應觸發事件。在許多情況下,調用此方法足以保證向 interestingEvent() 發出訊號。 希望接收事件通知的代碼必須實現 InterestingEvent 介面,並將自身引用傳遞給事件通知程式。 public class CallMe implements InterestingEvent
{
private EventNotifier en;public CallMe ()
{
// 建立事件通知程式,並將自身引用傳遞給它。
en = new EventNotifier (this);
}// 為事件定義實際的處理常式。
public void interestingEvent ()
{
// 噢!必定發生了感興趣的事件!
// 執行某些操作 ...
}//...
} JAVA的CALLBACK通過介面來實現。
例:
1.class A,class B
2.class A實現介面operate
3.class B擁有一個參數為operate介面類型的函數test(operate o)
4.class A運行時調用class B中test函數,以自身傳入參數
5.class B已取得A,就可以隨時回調A所實現的operate介面中的方法 public interface BoomWTC
{
//獲得拉登的決定
public benLaDengDecide(); // 執行轟炸世貿
public void boom();
}public class At$911 implements BoomWTC
{
private boolean decide;
private TerroristAttack ta; public At$911(){
Date now=new Date();
SimpleDateFormat myFmt1=new SimpleDateFormat("yy/MM/dd HH:mm");
this.dicede= myFmt.format(dt).equals("01/09/11 09:44");
this.ta=new TerroristAttack();
} //獲得拉登的決定
public boolean benLaDengDecide(){
return decide;
} // 執行轟炸世貿
public void boom(){
ta.attack(new At$911);
}
}public class TerroristAttack{
public TerroristAttack(){
} public attack(BoomWTC bmw){
if(bmw.benLaDengDecide()){
//let's go.........
}
}}
===================================================================
1. 什麼是回呼函數
回呼函數(callback Function),顧名思義,用於回調的函數。 回呼函數只是一個功能片段,由使用者按照回呼函數呼叫慣例來實現的一個函數。回呼函數是一個工作流程的一部分,由工作流程來決定函數的調用(回調)時機。回呼函數包含下面幾個特性:
1、屬於工作流程的一個部分;
2、必須按照工作流程指定的呼叫慣例來申明(定義);
3、他的調用時機由工作流程決定,回呼函數的實現者不能直接調用回呼函數來實現工作流程的功能;
2. 回調機制
回調機制是一種常見的設計模型,他把工作流程內的某個功能,按照約定的介面暴露給外部使用者,為外部使用者提供資料,或要求外部使用者提供資料。
=======================================================
java回調機制:
軟體模組之間總是存在著一定的介面,從調用方式上,可以把他們分為三類:同步調用、回調和非同步呼叫。
同步調用:一種阻塞式調用,調用方要等待對方執行完畢才返回,它是一種單向調用;
回 調:一種雙向調用模式,也就是說,被呼叫者在介面被調用時也會調用對方的介面;
非同步呼叫:一種類似訊息或事件的機制,不過它的調用方向剛好相反,介面的服務在收到某種訊息或發生某種事件時,會主動通知客戶方(即調用客戶方的介面)。
回調和非同步呼叫的關係非常緊密:使用回調來實現非同步訊息的註冊,通過非同步呼叫來實現訊息的通知。
========================================================
用Java裡的例子:
package callbackexample; public interface ICallBack { //需要回調的方法 public void postExec(); }
另外的一個類:
package callbackexample; public class FooBar { //組合彙總原則 private ICallBack callBack; public void setCallBack(ICallBack callBack) { this.callBack = callBack; doSth(); } public void doSth() { callBack.postExec(); } }
第二個類在測試類別裡面,是一個匿名類:
package callbackexample; public class Test { public static void main(String[] args) { FooBar foo = new FooBar(); foo.setCallBack(new ICallBack() { public void postExec() { System.out.println("在Test類中實現但不能被Test的對象引用,而由FooBar對象調用"); } }); } }
上訴的代碼:
1.兩個類:匿名類和FooBar
2.匿名類實現介面ICallBack(在test測試的main方法中用匿名類的形式實現)
3.FooBar 擁有一個參數為ICallBack介面類型的函數setCallBack(ICallBack o)
4.匿名類運行時調用FooBar中setCallBack函數,以自身傳入參數
5.FooBar已取得匿名類,就可以隨時回調匿名類中所實現的ICallBack介面中的方法
==================================
1。首先回調方法的概念與“構造方法”的概念是不一樣的,它不是指java中某個具有特殊意義或用途的方法。
2。稱它為方法的“回調”更恰當一些,它是指方法的一種調用方式。任何一個被“回調”的方法,皆可稱之為“回調方法”
3。方法的回調通常發生在“java介面”和“抽象類別”的使用過程中。
假設有介面名為 ICallBack 其中有方法名為postExec()
有類Myclass 實現了該介面,也就是一定實現了postExec()這個方法。現在有另一個類FooBar它有個方法 setCallBack(ICallBack callBack) ,並且setCallBack方法調用了callBack的postExec()方法。
如果現在,我們使用一個Myclass 的執行個體myClass,將它作為參數帶入到setCallBack(ICallBack callBack)方法中,我們就說setCallBack(ICallBack callBack)方法回調了myClass的postExec()方法。
==========================================================
========================================================================
其技巧就是:定義一個簡單介面,並在該介面中聲明我們要調用的方法。
下面舉一個例子:
假定我們希望在某個事件發生時得到通知。我們可以定義一個介面:
/*
* 在某個事件發生時得到通知.
*/
public interface InterestingEvent {
public void interestingEvent();
}
此介面中的方法,是個沒有傳回值的也沒有任何參數,如果您願意也可以有傳回值,也可以帶參數.這就要看具體需求而定.
這使得我們可以控制實現該介面的類的任何對象。因此,我們不必關心任何外部類型資訊。與在將 C++ 代碼用於Motif 時使用視窗小組件的資料域來容納對象指標的難以控制的 C 函數相比,這種方法要好得多。
實現介面的代碼如下:
public class CallMe implements InterestingEvent {
public CallMe() {
}
public void interestingEvent() {
System.out.println("發生了列印事件,哈哈");
}
}
public class CallYou implements InterestingEvent {
public CallYou() {
}
public void interestingEvent() {
System.out.println("發生了查詢事件,哈哈");
}
}
發出事件訊號的類必須等待實現了 InterestingEvent 介面的對象,並在適當時候調用 interestingEvent() 方法。
public class EventNotifier {
private InterestingEvent ie;
private boolean somethingHappened ;
public EventNotifier() {
somethingHappened = true ;
}
public void setInterestingEvent(InterestingEvent ie){
this.ie = ie ;
}
public void doWork(){
if(somethingHappened){
ie.interestingEvent();
}
}
}
下面做一下測試.
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
CallMe cm = new CallMe();
CallYou cy = new CallYou();
EventNotifier en = new EventNotifier();
en.setInterestingEvent(cm);
en.doWork();
en.setInterestingEvent(cy);
en.doWork();
}
}
此測試在發生指定的調用CalMe事件時,就掃行CallMe下的命令,如發生CallYou事件時,就調用CallYou下的命令.此種方法可以結合Command模式.實現MS-Windows 和 X Window System 事件驅動編程模型.