事件監聽機制——Java vs. C#
C#語言類似Java,但兩者之間的差別還是顯而易見的,比如下面要說到的——事件監聽機制。
Java的事件監聽機制
Java中的事件監聽是整個Java消息傳遞的基礎和關鍵。其中涉及三類對象:事件源(Event Source)、事件(Event)、事件監聽器(Event Listener)。
- 事件源:事件發生的場所,通常就是各個組件,比如一個按鈕,或者編輯框等。
- 事件:描述事件源狀態改變的對象。
- 事件監聽器:負責監聽事件源所發生的事件,並對各種事件做出相應的響應。
下面來看一個完整模型的demo:
/*
* 事件
*/
public interface IEvent {
void setEventListener(IEventListener arg);
boolean ClickButton();
boolean MoveMouse();
}
/*
* 事件監聽器,調用事件處理器
*/
public interface IEventListener {
void doEvent(IEvent arg);
}
/*
* 事件源:事件發生的地點
*/
public class EventSource implements IEvent{
private IEventListener mEventListener;
boolean button;
boolean mouse;
//註冊監聽器
@Override
public void setEventListener(IEventListener arg){
mEventListener = arg;
}
//觸發事件
public void mouseEventHappened(){
mouse = true;
mEventListener.doEvent(this);
}
@Override
public boolean ClickButton() {
return button;
// TODO Auto-generated method stub
}
@Override
public boolean MoveMouse() {
// TODO Auto-generated method stub
return mouse;
}
}
public class EventSource2 implements IEvent {
private IEventListener ml;
boolean button;
boolean mouse;
@Override
public void setEventListener(IEventListener arg) {
ml = arg;
}
@Override
public boolean ClickButton() {
// TODO Auto-generated method stub
return button;
}
@Override
public boolean MoveMouse() {
// TODO Auto-generated method stub
return mouse;
}
// 觸發事件
public void buttonEventHappened() {
button = true;
ml.doEvent(this);
}
}
public class Test {
public static void main(String[] args) {
// 事件源(被監聽的對象)
EventSource m1 = new EventSource();
EventSource2 m2 = new EventSource2();
// 監聽器
IEventListener mEventListener = new IEventListener() {
@Override
public void doEvent(IEvent arg) {
if (true == arg.ClickButton()) {
System.out.println("你點擊了按鈕");
}else if(true == arg.MoveMouse()){
System.out.println("你移動了鼠標");
}
}
};
// 註冊監聽器到事件源
m1.setEventListener(mEventListener);
m1.mouseEventHappened();
// 註冊監聽器到事件源
m2.setEventListener(mEventListener);
m2.buttonEventHappened();
}
}
C# 事件監聽
對於熟悉Java的小夥伴,第一次接觸 C# 的委託(delegate)和事件(event)可能會比較困惑,其實這跟Java的監聽、事件是等同的,只是表述上不同罷了。委託其實就是“方法模板”,就好像“類”是“對象”的模板一樣。
委託+事件是觀察者模式的一個典型例子,所謂的委託其實就是觀察者,它會關心某種事件,一旦這種事件被觸發,這個觀察者就會行動。
事件的聲明過程:
- 存在已經聲明的事件委託,該委託位於 namespace 下,可全局訪問;
- 在數據類型中利用event和事件委託來聲明事件,並聲明事件觸發方法;
- 事件綁定,利用事件聲明的對象實例,聲明符合委託簽名的方法,利用 += 或 -= 來進行事件的綁定和解除;
- 事件觸發,代碼利用事件聲明中的觸發事件的方法即可。
用 C# 實現的事件監聽的demo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Event
{
class Program
{
static void Main(string[] args)
{
myChangedEvent mce = new myChangedEvent();
myEventListener mel = new myEventListener(mce);
mce.ToString();
mel.detach();
mce.ToString();
}
}
public delegate void myEventHandler(object s,EventArgs e); //聲明自定義的事件委託,用來執行事件的聲明,和處理方法的傳遞
class myChangedEvent
{
public event myEventHandler Changed; //利用委託來聲明事件
protected virtual void OnChanged(EventArgs e) //聲明事件觸發的方法
{
if (Changed != null)
Changed(this, e); //觸發事件
}
public override string ToString()
{
OnChanged(EventArgs.Empty); //調用事件觸發方法
return "執行ToString";
}
}
class myEventListener //聲明事件監聽的類型,併爲以上聲明事件傳入處理方法
{
private myChangedEvent mce;
public myEventListener(myChangedEvent Mce)
{
mce = Mce; //利用構造函數,獲得對象的引用
mce.Changed += new myEventHandler(ListenerChanged); //爲其事件添加自定義的處理方法
}
private void ListenerChanged(object s,EventArgs e) //聲明一個符合事件委託簽名的處理方法
{
Console.WriteLine("已經觸發事件!");
}
public void detach()
{
mce.Changed -= new myEventHandler(ListenerChanged);
}
}
}