首頁  >  文章  >  Java  >  Java如何實作事件驅動機制的實例

Java如何實作事件驅動機制的實例

黄舟
黄舟原創
2017-09-05 10:13:312191瀏覽

這篇文章主要介紹了淺談用java實現事件驅動機制,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧

由於專案需求,需要為Java提供一套支援事件驅動機制的類別庫,可以實作類似C#中的event和delegate機制。眾所周知,Java語言本身以及其標準庫中並沒有提供事件驅動機制的相關接口,雖然Swing(我且認為其不屬於標準庫,因為一般沒人用:)中存在相關的類支持該機制以實現組件的事件處理,但它畢竟是與GUI相耦合的,而在其它類型的應用程式中使用起來顯得就有些彆扭,缺乏通用性。因此有必要實作一套通用的Java事件驅動機制類別庫,然後將其應用於通用的Java應用程式當中,雖然這並不是什麼難事:)

讓我們先考察C#的事件驅動機制編寫方法。 C#中提供的event關鍵字可以很容易的用來定義一個事件,然後透過在事件中加入事件處理函數(在C#中一般用委託(delegate)來引用一個函數),觸發事件就可以呼叫相關的處理函數,也即是事件驅動的過程。例如:


//定义事件和对应的委托
public event MyDelegate Click;
public delegate void MyDelegate();

//定义委托
void OnClick(){
  console.writeline("you just clicked me!");
}

//将委托与事件关联
Click += OnClick;

//触发事件
Click();

上面的程式碼就是用C#實現的事件驅動機制的一個簡單的例子,可見是非常簡單的,這都源自於C#在語言層面(其實是CLR)提供的便利。遺憾的是Java並沒有提供這樣的便利,需要人為實現。以下本文將提供兩種實作事件驅動機制的方法,僅供參考。

觀察者模式

#觀察者模式是一種常用的設計模式,觀察者(Observer)先透過訂閱被觀察對象(Subject),這樣一旦被觀察者(Subject)發生某種變化,就會將變化通知觀察者(Observer)。

這種設計模式剛好可以用於事件驅動機制,事件(event)相當於被觀察對象(Subject),一旦事件被觸發,就會呼叫事件處理函數,可見事件處理函數(C#中的委託)可以看作是觀察者。因此可以像如下這樣實現上文中的功能。


/*事件类*/
public Event {
  //与事件相关的事件处理函数
  public ArrayList<Callback> callbackList;
  
  //事件触发函数
  public void emit(){
    for(Callback cb : callbackList){
      cb.run();
    }
  }
  
  //注册事件处理函数
  public registerCallback(Callback cb){
    callbackList.add(cb);
  }
}

/*事件处理函数类*/
public interface Callback {
  void run();
}

public OnClick implements Callback {
  //函数
  public void run(){
    System.out.println("you just clicked me!");
  }
  
  
/*实现事件驱动*/
Event e = new Event(); 
//将OnClick事件处理函数注册到事件中
e.registerCallback(new OnClick()); 
//触发事件
e.emit();

上面的Java程式碼實作了一個簡單的事件驅動機制,原理很簡單,是典型的觀察者模式的應用案例。

利用反射

Java語言提供強大的反射功能,可以在執行時取得類別的各個組成部分(例如類別名稱、類別成員函數、類別屬性等等)並對其進行操作。以下使用反射來實現簡單的事件驅動機制。


/*事件处理类*/
public class EventHandler {
  //事件源
  private Object sender;
  //事件处理函数名称(用于反射)
  private String callback;
  
  public EventHandler(Object sender, String callback){
    this.sender = sender;
    this.callback = callback;
  }
  
  //事件触发
  public void emit(){
  Class senderType = this.sender.getClass();
  try {
    //获取并调用事件源sender的事件处理函数
    Method method = senderType.getMethod(this.callback);
    method.invoke(this.sender);
    } catch (Exception e2) {
      e2.printStackTrace();
    }
  }
}


/*事件源*/
public class Button(){
  /*可以在此设置Button类的相关属性,比如名字等*/
  private String name;
  ...
  
  
  //事件处理函数
  public void onClick(){
    System.out.println("you just clicked me!");
  }
}
  
  
/*实现事件驱动机制*/
Button b = new Button();
if(/*收到按钮点击信号*/){
  EventHandler e = new EventHandler(b, "onClick");
  e.emit();
}

上述程式碼展示了利用反射實現的事件驅動機制,利用反射機制的好處是其具有強大的擴展性,例如我的事件處理函數中可以引入一個EventArgs的形參,從而可以讓事件本身帶有參數,這樣就可以讓事件攜帶更多的信息,改寫後的事件處理函數如下方的代碼所示:


public class EventArgs {
  //参数
  String p1;
  Integer p2;
  ...
  
}

//onClick事件处理函数改写
public void onClick(Object sender, EventArgs e){
  //参数e提供更多的信息
  System.out.println("Hello, you clicked me! " + e.p1 + e.p2);
}

//触发函数emit改写
public void emit(EventArgs e){
Class senderType = this.sender.getClass();
try {
  //获取并调用事件源sender的事件处理函数
  Method method = senderType.getMethod(this.callback, this.getClass(), e.getClass());
  method.invoke(this.sender, this.sender, e);
  } catch (Exception e2) {
    e2.printStackTrace();
  }
}

是不是似曾相識?沒錯,和用C#寫Winform窗體時,Visual studio為你自動產生的事件處理函數(程式碼中的onClick函數)幾乎具有完全相同的形式,但此時我們是用Java實現的。

當然,除了上述提到的兩種方法可以實現Java的事件驅動機制以外,還有一些其它的方法,例如可以利用Java的內部類別來實現,筆者也曾寫過一些範例程式碼,這裡就不再冗餘了,留待以後再講。

以上是Java如何實作事件驅動機制的實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn