程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 觀察者模式的java實現

觀察者模式的java實現

編輯:關於JAVA

Java事件模型

在我的前兩篇介紹C#事件和委托的blog 發表之後,大家響應特別熱烈,點擊率很高,看來事件/委托機制是很多同仁比較模糊的地方,借此東風,加上最近自己轉戰java,於是決定寫這篇介紹java事件機制的blog。

其實,不管哪種語言的事件機制,毫無例外都逃不出三點:事件源/發送者,事件的接受者/處理者/偵聽者,以及事件源向事件接受者傳遞的事件信息。對應在java中,事件源 (event source),事件傾聽者 (event listener),事件消息稱為eventobject。而在C#中,分別是發送者(Sender),處理者(handler),事件消息則是事件參數(EventArgument)。而java和c#都采用相同的響應模式:發布者/訂閱者模式(publisher/subscriber),具體來說就是:

(1)訂閱者向發布者注冊自己感興趣的事件;

(2)事件發生時,通知訂閱者響應事件。

簡單一句話,就是那句常說的:“Don't call me,I'll call you。”

由於之前已經對C#的事件機制進行了探討,下面,我將著重談談java的事件機制,以及對兩者實現機制的比較:

(一)Java事件實現機制

下面是一個自定義java事件的例子,通過這個簡單的演示,你可以看到Java的事件實現機制。這裡說明一下,這個例子引自http://www.rainsts.net/article.asp?id=224,為了說明原理,改編了原文中對匿名方法部分,而且由於這個網站的代碼編輯器缺乏對java代碼的支持,因此,對關鍵字,類型等並沒有作格式顯示處理。

import java.util.*;
// 定義一個類似 C# EventArgs 的類用來傳遞事件狀態信息。
// 一般要求繼承自 java.util.EventObject,且以 Event 結尾。
class ClicktEvent extends EventObject
{
  public DemoBean source;
  //構造函數的參數傳遞產生事件的事件源
  public ClickEvent(DemoBean source)
  {
   super(source);
   this.source = source;
  }
}
// 通過接口來定義事件響應函數原型,就像c# delegate定義了響應函數的“模板”,
// 別忘了,接口實際上就是一種“合同”,“契約”,通過這個接口中的函數簽名達到對響應函數的規范
// 一般要求繼承自 java.util.EventListener,且以 Listener 結尾。
//這裡以I開頭定義ClickListener接口,借鑒自.net,不符合j2ee的命名規范
interface IClickListener extends EventListener
{
  void click(ClicktEvent e);
}

//事件偵聽者,實現偵聽者接口
public class ClickListener implements IClickListener
{
   public void click(ClicktEvent e)   {
    System.out.println( "the clicked event happened");
   }

 }
// 定義演示控件類,也就是事件源
class DemoBean
{
 // 用一個java.util.Vector對象來存儲所有的事件監聽器對象。
 private Vector clicks = new Vector();
 // 添加事件訂閱。一般以 add( listener)方式拼寫,並添加 synchronized 關鍵字。
 public synchronized void addExampleListener(IClickListener listener)
 {
  clicks.add(listener);
 }
 // 移除事件訂閱。一般以 remove( listener)方式拼寫,並添加 synchronized 關鍵字。
 public synchronized void removeExampleListener(IClickListener listener)
 {
  clicks.remove(listener);
 }
 // 觸發事件。
 protected void doClickEvent()
  {
  // 鎖定,避免在觸發期間有事件被訂閱或移除。
  synchronized (this)
   {
   // 創建事件狀態對象。
   ClicktEvent ce = new ClickEvent(this);
   // 循環觸發所有的事件訂閱方法。
   for (int i = 0; i < clicks.size(); i++)
    {
     IClickListener e = (IClickListener)clicks.get(i);
     e.click(ce);
    }
   }
 }
 // 模擬點擊操作。
 public void Click()
 {
  doClickEvent();
 }
}

//測試程序
public class Program
{
 public static void main(String[] args)
 {
  // 創建控件。
  DemoBean bean = new DemoBean();

  //實例化一個事件偵聽者
  ClickListner testListner=new ClickListner();
  // 添加事件訂閱。
  bean.addExampleListener (testListner);
  // 模擬觸發點擊操作。
  bean.Click();
 }
}

輸出結果:the clicked event happened

(二)事件實現機制的比較(Java/C#)

總體來說,c#沿襲了C/C++中的函數回調機制,通過委托對函數指針的封裝來實現對響應函數的調用;而java則通過接口來規范響應函數,使用多態的方式在運行時實現對事件接收者的響應函數的調用,應該說,這才是一種面向對象的機制。當然,兩種方式各有千秋,下表是對兩者的比較:

  java c# 說明 效率 采用多態,相對高 采用委托,相對低。 應該說,它們都是在運行時獲取對哪個對象的哪個方法進行調用,但是采用多態相對於委托效率高一點。 是否支持靜態方法調用 否 是 java采用多態,當然不能把方法聲明為static;c#中delegate中的_object可以為null來實現對靜態方法的調用 是否類型安全 是 是 它們都會在編譯時對響應函數進行參數檢查,類型安全。 開發者易用性 兩級實體對象:事件源-與事件響應者 三級實體對象:事件源-委托-事件響應者 由於有delegate的封裝,不用編寫事件注冊/注銷之類的代碼,c#事件處理易用性相對高;注意,雖然java中采用接口來規范響應函數,但這裡卻說java中是兩級實體對象,是因為在運行時並不存在接口的實例(實際上,接口也不可實例化,呵呵)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved