導航:首頁 > 編程語言 > java事件監聽機制

java事件監聽機制

發布時間:2023-05-03 13:10:09

java設計模式-回調、事件監聽器、觀察者模式

轉自( https://my.oschina.net/u/923324/blog/792857 )

背景
關於設計模式,之前筆者寫過工廠模式,最近在使用gava ListenableFuture時發現事件監聽模型特別有意思,於是就把事件監聽、觀察者之間比較了一番,發現這是一個非常旁春重要的設計模式,在很多框架里扮演關鍵的作用。

回調函數
為什麼首先會講回調函數呢?因為這個是理解監聽器、觀察者模式的關鍵。

什麼是回調函數
所謂的回調,用於回調的函數。 回調函數只是一個功能片段,由用戶按照回調函數調用約定來實現的一個函數。 有這么一句通俗的定義:就是程序員A寫了一段程序(程序a),其中預留有回調函數介面,並封裝好了該程序。程序員B要讓a調用自己的程序b中的一個方法,於是,他通過a中的介面回調自己b中的方法。

舉個例子:
這里有兩個實體:回調抽象介面、回調者(即程序a)

回調介面(ICallBack )
public interface ICallBack {
public void callBack();
}
回調者(用於調用回調函數的類)
public class Caller {

}
回調測試:
public static void main(String[] args) {
Caller call = new Caller();
call.call(new ICallBack(){

控制台輸出:

start...

終於回調成功了!

end...

還有一種寫法

或實現這個ICallBack介面類

class CallBackC implements ICallBack{
@Override
public void callBack() {
System.out.println("終於回調成功了!");
}
}
有沒有發現這個模型和執行一個線程,Thread很像。 沒錯,Thread就是回調者,Runnable就是一個回調介面。

new Thread(new Runnable(){
@Override
public void run() {
System.out.println("回調一個新線程!");
}}).start();
Callable也是一個回調介面,原來一直在用。 接下來我們開始講事件監聽器

事件監聽模式
什麼是事件監聽器
監聽器將監聽自己感興趣的事件一旦鎮啟顫該事件被觸發或改變,立即得到通知,做出響應。例如:android程序中的Button事件。

java的事件監聽機制可概括為3點:

java的事件監聽機制涉及到 事件御敗源,事件監聽器,事件對象 三個組件,監聽器一般是介面,用來約定調用方式
當事件源對象上發生操作時,它將會調用事件監聽器的一個方法,並在調用該方法時傳遞事件對象過去
事件監聽器實現類,通常是由開發人員編寫,開發人員通過事件對象拿到事件源,從而對事件源上的操作進行處理
舉個例子
這里我為了方便,直接使用jdk,EventListener 監聽器,感興趣的可以去研究下源碼,非常簡單。

監聽器介面
public interface EventListener extends java.util.EventListener {
//事件處理
public void handleEvent(EventObject event);
}

事件對象
public class EventObject extends java.util.EventObject{
private static final long serialVersionUID = 1L;
public EventObject(Object source){
super(source);
}
public void doEvent(){
System.out.println("通知一個事件源 source :"+ this.getSource());
}

}
事件源
事件源是事件對象的入口,包含監聽器的注冊、撤銷、通知

public class EventSource {
//監聽器列表,監聽器的注冊則加入此列表
private Vector<EventListener> ListenerList = new Vector<EventListener>();
//注冊監聽器
public void addListener(EventListener eventListener){
ListenerList.add(eventListener);
}
//撤銷注冊
public void removeListener(EventListener eventListener){
ListenerList.remove(eventListener);
}
//接受外部事件
public void notifyListenerEvents(EventObject event){
for(EventListener eventListener:ListenerList){
eventListener.handleEvent(event);
}
}

}

測試執行
public static void main(String[] args) {
EventSource eventSource = new EventSource();

}
控制台顯示:

通知一個事件源 source :openWindows

通知一個事件源 source :openWindows

doOpen something...

到這里你應該非常清楚的了解,什麼是事件監聽器模式了吧。 那麼哪裡是回調介面,哪裡是回調者,對!EventListener是一個回調介面類,handleEvent是一個回調函數介面,通過回調模型,EventSource 事件源便可回調具體監聽器動作。

有了了解後,這里還可以做一些變動。 對特定的事件提供特定的關注方法和事件觸發

public class EventSource {
...
public void onCloseWindows(EventListener eventListener){
System.out.println("關注關閉窗口事件");
ListenerList.add(eventListener);
}

}
public static void main(String[] args) {
EventSource windows = new EventSource();
/**
* 另一種實現方式
*/
//關注關閉事件,實現回調介面
windows.onCloseWindows(new EventListener(){

}
這種就類似於,我們的窗口程序,Button監聽器了。我們還可以為單擊、雙擊事件定製監聽器。

觀察者模式
什麼是觀察者模式
觀察者模式其實原理和監聽器是一樣的,使用的關鍵在搞清楚什麼是觀察者、什麼是被觀察者。

觀察者(Observer)相當於事件監器。有個微博模型比較好理解,A用戶關注B用戶,則A是B的觀察者,B是一個被觀察者,一旦B發表任何言論,A便可以獲得。
被觀察者(Observable)相當於事件源和事件,執行事件源通知邏輯時,將會回調observer的回調方法update。
舉個例子
為了方便,同樣我直接使用jdk自帶的Observer。

一個觀察者
public class WatcherDemo implements Observer {
@Override
public void update(Observable o, Object arg) {
if(arg.toString().equals("openWindows")){
System.out.println("已經打開窗口");
}
}
}
被觀察者
Observable 是jdk自帶的被觀察者,具體可以自行看源碼和之前的監聽器事件源類似。

主要方法有

addObserver() 添加觀察者,與監聽器模式類似
notifyObservers() 通知所有觀察者
類Watched.java的實現描述:被觀察者,相當於事件監聽的事件源和事件對象。又理解為訂閱的對象 主要職責:注冊/撤銷觀察者(監聽器),接收主題對象(事件對象)傳遞給觀察者(監聽器),具體由感興趣的觀察者(監聽器)執行

/**

}
測試執行
public static void main(String[] args) {
Watched watched = new Watched();
WatcherDemo watcherDemo = new WatcherDemo();
watched.addObserver(watcherDemo);
watched.addObserver(new Observer(){
@Override
public void update(Observable o, Object arg) {
if(arg.toString().equals("closeWindows")){
System.out.println("已經關閉窗口");
}
}
});
//觸發打開窗口事件,通知觀察者
watched.notifyObservers("openWindows");
//觸發關閉窗口事件,通知觀察者
watched.notifyObservers("closeWindows");

控制台輸出:

已經打開窗口

已經關閉窗口

總結
從整個實現和調用過程來看,觀察者和監聽器模式基本一樣。

有興趣的你可以基於這個模型,實現一個簡單微博加關注和取消的功能。 說到底,就是事件驅動模型,將調用者和被調用者通過一個鏈表、回調函數來解耦掉,相互獨立。

「你別來找我,有了我會找你」。

整個設計模式的初衷也就是要做到低耦合,低依賴。

再延伸下,消息中間件是什麼一個模型? 將生產者+服務中心(事件源)和消費者(監聽器)通過消息隊列解耦掉. 消息這相當於具體的事件對象,只是存儲在一個隊列里(有消峰填谷的作用),服務中心回調消費者介面通過拉或取的模型響應。 想必基於這個模型,實現一個簡單的消息中間件也是可以的。

還比如gava ListenableFuture,採用監聽器模式就解決了future.get()一直阻塞等待返回結果的問題。

有興趣的同學,可以再思考下觀察者和責任鏈之間的關系, 我是這樣看的。

同樣會存在一個鏈表,被觀察者會通知所有觀察者,觀察者自行處理,觀察者之間互不影響。 而責任鏈,講究的是擊鼓傳花,也就是每一個節點只需記錄繼任節點,由當前節點決定是否往下傳。 常用於工作流,過濾器web filter。

⑵ java 滑鼠左鍵 加 ctrl 選中是什麼監聽事件

事件源。
java的事件監聽機制包含三個組件事件源事件監聽器事件對象,當事件源上發生操作,時它將會調用事件監聽器的一個方法,並且會傳遞一個事件對象過來,事件監聽器由開發人員編寫,開發人員在事件監聽器中,可以拿到事件源,從而對事件源上的操作進行處理。

⑶ 簡述java事件處理機制

java事件處理機制你必須得明確以下幾個概念:
核心:java採用的是事件源——事件監聽器模型
1:事件(event):是指一個狀態的改變,或者一個活動的發生。例如,簡單常見的是單擊一個按鈕,或者輸入一個按鍵都是一個事件。
2:事件源(event source):能夠產生事件的對象稱為事件源,如文本框,按鈕,下拉列表等。
3:事件監聽器(event listener):需要一個對象對事件源進行監聽,以便對發生的事件做出處理,該對象就是事件監聽器。事件源通過調用相應的方法將某個對象作為自己的監聽器。無論應用程序還是小程序都採用這一機制。
例,對於按鈕,注冊監聽器的方法是 addActionListener(監視器);:
4: 事件源獲得監聽器之後,相應的操作就會導致事件的發生,並通知監聽器,監聽器就會做出相應的處理。
5:處理事件的介面:監聽器負責處理事件源發生的事件。為了處理事件源發生的事件,監聽器會自動調用一個方法來處理事件,該方法定義在相應事件的介面中。

⑷ 在java事件中。WindowEvent與WindowListener的區別是什麼

Event就是事件,listener就是監聽器,用於監聽事件,即當發生某個事件時觸發一些操作。
事件監聽機制如下:
監聽源比如一個按鈕,調用addMouseListener,為其自身添加一個滑鼠監聽器,那麼在該按鈕上發生的相關滑鼠事件比如滑鼠按下,松開等將通知到該監聽器,同時回調該監聽器的相應方法。UI程序也是通過這樣的方式來處理這些界面事件的。
同樣的道理,WindowEvent和WindowListener你應該可以明白是做什麼的了,就是窗口事件和窗口事件的監聽器。窗口事件就比如窗口最大化最小化之類。

⑸ java的listener是什麼原理

回調,


Java的事件監聽機制是這樣的:

事件的觀察者向事件的發出者進行注冊,當事件發生時,事件的發出者調用之前注冊的洞禪回調函數,將相關事件信息通知到事件的觀察者。這個過程中,當然不用事件的觀察者進行輪詢。

你可能有個問題:那麼事件的發出者如何得知事件發生呢?實際上舉個例子來說如窗口類,有個窗口關閉事件可以注冊,作為窗口類來說內部有相關關閉窗口的方法,只要這些方法被調用,當然就知道窗口被關閉了,只要這些方法在合適的時機調用回調函數即可。

事件的觀察者可以沒有,有一個或多個,只要再事件的發出者內部維護一個List<XxxListener>即可,到時候迭代列表依次發出事件即可。(這里一般不設計為多線程,而是單線程依次發送,所以事件處理函數最好不要阻塞太長時間,否則會影響到下一個觀察者,甚至事件發出方代碼的調用)



Java 事件處理方法是基於授權事件模型
事件源生成事件並將其發送至一個或多個監聽器
監聽器簡單地等待,直到它收到一個事件。一旦事件被接受,監聽器將處理這些事件,然後返回。

事件:在授權事件模型中,事件是一個描述事件源狀態改變的對象 。
通過滑鼠、鍵盤與 GUI 界面直接或間接交互都會生成事件。 如:按下一個按鈕、通過鍵盤輸入一個字元、選擇列表框中的一項、點擊一下滑鼠等。

事件源鍵鍵:事件源是一個生成事件的對象
一個事件源可能會生成不同類型的事件
事件源提供了一組方法,用於為事件注冊一個或多個監聽器。
每種事件的類型都有其自己的注冊方法。一般形式為:
public void add<EventType>Listener (TypeListener e)

AWT採取的事件控制過程:監聽器對象屬於一個類的實例,這個類實現了一個特殊的介面,名為「監聽者介面」
事件源是一個對象,它可以注冊一個或多個監聽器對象,並向其發送事件對象。
事件源將在發生事件時向所有注冊的監聽器發送事件對象。
監聽器對象使用事件對象中的信息來確定它們納亮塵對事件的響應

事件模型:
1.基於代理(授權)事件模型
事件處理是一個事件源授權到一個或者多個事件監聽器。其基本原理是:組件激發事件,事件監聽器監聽和處理事件,可以調用組件的add<EventType>Listener方法向組件注冊監聽器。把其加入到組件以後,如果組件激發了相應類型的事件,那麼定義在監聽器中的事件處理方法會被調用。

2.此模型主要由以三種對象為中心組成
事件源 由它來激發產生事件
是產生或拋出事件的對象。
事件監聽器 由它來處理事件
實現某個特定EventListener 介面,此介面定義了一種或多種方法,事件源調用它們以響應該介面所處理的每一種特定事件類型 。
事件 具體的事件類型
事件類型封裝在以java.util.EventObject為根的類層次中。當事件發生時,事件記錄發生的一切事件,並從事件源傳播到監聽器對象



⑹ java中的事件監聽是怎樣實現隨時監聽的,是通過線程嗎

java中的事件監聽不是通過線程實現的,它是通過一種注冊--通知機制實現的。在專java的設計模式中,有一種模屬式叫:觀察者模式,和這個類似。

⑺ 淺析Java與C#的事件處理機制(一)

Java與C#的事件處理都是實現了事件源 事件響應者機制 但又不完全相同 Java實現的是一種事件源與事件響應者兩級實體對象方式 這里的事件響應者也是事件監聽者 而C#實現的是一種事件源 代理 事件響應者三級實體對象方式 下面就這兩種方式來具體說明

Java事件處理

從概念上講 事件是一種在 源對象 和 監聽者對象 之間 某種狀態發生變化的傳遞機制 事件有許多不同的用途 例如在Windows系統中常要處理的滑鼠事件 窗口邊界改變事件 鍵盤事件等 在Java中則是定義了一個普通的 可擴充的事件機制 這種機制能夠

對事件類型和傳遞的模型的定義和擴充提供一個公共框架 並適合於廣泛的應用

與Java語言和環境有較高的集成度

事件能被描述環境捕獲和觸發

能使其它構造工具採取某種技術在設計時直接控制事件 以及事件源和事件監聽者之間的聯系

事件機制本身不依賴於復雜的開發工具

事件從事件源到監聽者的傳遞是通過對目標監聽者對象的Java方法調用進行的 對每個明確的事件的發生 都相應地定義一個明確的Java方法 這些方法都集中定義在事件監聽者(EventListener)介面中 這個介面要繼承java util EventListener 實現了事件監聽者介面中一些或全部方法的類就是事件監聽者 伴隨著事件的發生 相應的狀態通常都封裝在事件狀態對象中 該對象必須繼承自java util EventObject 事件狀態對象作為單參傳遞給應響應該事件的監聽者方法中 發出某種特定事件的事件源的標識是 遵從規定的設計格式為事件監聽者定義注冊方法 並接受對指定事件監聽者介面實例的引用 有時 事件監聽者不能直接實現事件監聽者介面 或者還有其它的額外動作時 就要在一個源與其它一個或多個監聽者之間插入一個事件適配器類的實例 來建立它們之間的聯系

事件狀態對象(Event State Object)

與事件發生有關的狀態信息一般都封裝在一個事件狀態對象中 這種對象是java util EventObject的子類 按設計習慣 這種事件狀態對象類的名應以Event結尾 例如

public class MouseMovedExampleEvent extends java util EventObject{ protected int x y /*創建一個滑鼠移動事件MouseMovedExampleEvent */MouseMovedExampleEvent(java awt Component source Point location) {super(source);x = location x;嫌銀攜y = location y;}/* 獲取滑鼠位置*/public Point getLocation() {return new Point(x y);}}

事件監聽者介面(芹伏EventListener Interface)與事件監聽者

由於Java事件模型是基於方法調用 因而需要一個定義並組織事件操縱方法的方式 事件操縱方法都被定義在繼承了java util EventListener類的EventListener介面中 按規定 EventListener介面的命名要以Listener結尾 任何一個類如果想操縱在EventListener介面中定義的方法都必須以實現這個介面方式進行 這個類也就是事件監聽者 例如

搏歲/*先定義了一個滑鼠移動事件對象*/public class MouseMovedExampleEvent extends java util EventObject {// 在此類中包含了與滑鼠移動事件有關的狀態信息 }/*定義了滑鼠移動事件的監聽者介面*/interface MouseMovedExampleListener extends java util EventListener {/*在這個介面中定義了滑鼠移動事件監聽者所應支持的方法*/void mouseMoved(MouseMovedExampleEvent mme);}

在介面中只定義方法名 方法的參數和返回值類型 如 上面介面中的mouseMoved方法的具體實現是在下面的ArbitraryObject類中定義的

class ArbitraryObject implements MouseMovedExampleListener {public void mouseMoved(MouseMovedExampleEvent mme){ }}

ArbitraryObject就是MouseMovedExampleEvent事件的監聽者

事件監聽者的注冊與注銷

為了各種可能的事件監聽者把自己注冊入合適的事件源中 建立源與事件監聽者間的事件流 事件源必須為事件監聽者提供注冊和注銷的方法 在前面的bound屬性介紹中已看到了這種使用過程 在實際中 事件監聽者的注冊和注銷要使用標準的設計格式

public void add< ListenerType>(< ListenerType> listener) public void remove< ListenerType>(< ListenerType> listener)

首先定義了一個事件監聽者介面

public interface ModelChangedListener extends java util EventListener {void modelChanged(EventObject e);}

接著定義事件源類

lishixin/Article/program/net/201311/14840

⑻ java監聽器原理



  1. 一個事件源可能會生成不同類型的事件,事件源提供了一組方法,用於為事件注冊一個或多個監聽器。

  2. 每種事件的類型都有其自己的注冊方法。一般形式為:publicvoidadd<EventType>Listener(TypeListenere)

  3. AWT採取的事件控制過程:監聽器對象屬於一個類的實例,這個類實現了一個特殊的介面,名為「監聽者介面」

  4. 事件源是一個對象,它可以注冊一個或多個監聽器對象,並向其發送事件對象。

  5. 事件源將在發生事件時向所有注冊的監聽器發送事件對象。

  6. 監聽器對象使用事件對象中的信息來確定它們對事件的響應


  1. 基於代理(授權)事件模型,事件處理是一個事件源授權到一個或者多個事件監聽器。其基本原理是:組件激發事件,事件監聽器監聽和處理事件,可以調用組件的add<EventType>Listener方法向組件注冊監聽器。把其加入到組件以後,如果組件激發了相應類型的事件,那麼定義在監聽器中的事件處理方法會被調用。


  1. 事件源由它來激發產生事件

  2. 是產生或拋出事件的對象。

  3. 事件監聽器由它來處理事件

  4. 實現某個特定EventListener介面,此介面定義了一種或多種方法,事件源調用它們以響應該介面所處理的每一種特定事件類型。

  5. 事件具體的事件類型

  6. 事件類型封裝在以java.util.EventObject為根的類層次中。當事件發生時,事件記錄發生的一切事件,並從事件源傳播到監聽器對象

⑼ java 自定義事件的觸發及監聽

JAVA事件響應機制

1,先自定義一個事件

public class MyEvent extends java.util.EventObject{
public MyEvent(Object source)
{
super(source);
}
}

2,再自定義一個監聽器

public class MyListener implements java.util.EventListener{
//這里是當事件發生後的響應過程
public void EventActivated(MyEvent me)
{
System.out.println("事件已經被觸發");
}
}

3,以下這個類為觸發事件的事件源

public class MyObject {
private Vector vectorListeners=new Vector();

public synchronized void addMyListener(MyListener ml)
{
vectorListeners.addElement(ml);
}

public synchronized void removeMyListener(MyListener ml)
{
vectorListeners.removeElement(ml);
}

protected void activateMyEvent()
{
Vector tempVector=null;

MyEvent e=new MyEvent(this);

synchronized(this)
{
tempVector=(Vector)vectorListeners.clone();

for(int i=0;i<tempVector.size();i++)
{
MyListener ml=(MyListener)tempVector.elementAt(i);
ml.EventActivated(e);
}
}

}

//定義一個公用方法用於觸發事件
public void test()
{
activateMyEvent();
}
}

4,測試類

public class Test {

public static void main(String[] args)
{
MyObject mo=new MyObject();

//注冊該事件
mo.addMyListener(new MyListener());

//觸發該事件
mo.test();
}
}

閱讀全文

與java事件監聽機制相關的資料

熱點內容
桌面雲配置文件分離 瀏覽:505
iphone5如何升級4g網路 瀏覽:5
團購是在哪個app 瀏覽:897
打開多個word文檔圖片就不能顯示 瀏覽:855
騰訊新聞怎麼切換版本 瀏覽:269
app安裝失敗用不了 瀏覽:326
桌面文件滑鼠點開會變大變小 瀏覽:536
手機誤刪系統文件開不了機 瀏覽:883
微信兔子甩耳朵 瀏覽:998
android藍牙傳文件在哪裡 瀏覽:354
蘋果6s軟解是真的嗎 瀏覽:310
c語言代碼量大 瀏覽:874
最新網路衛星導航如何使用 瀏覽:425
以下哪些文件屬於圖像文件 瀏覽:774
zycommentjs 瀏覽:414
確認全血細胞減少看哪些數據 瀏覽:265
文件有哪些要求 瀏覽:484
cad打開時會出現兩個文件 瀏覽:65
什麼是轉基因網站 瀏覽:48
手柄設備有問題代碼43 瀏覽:921

友情鏈接