对Java和C#事件机制的理解

最近在重新研究c#,发现c#的事件机制和java的事件机制是不同的.原因是c#中的事件是通过委托来实现的,而java中事件是通过适配器来实现的.
在网上搜索些资料时发现博客园Jeffrey Lee的文章中有这么一篇文章<对Java和C#事件机制的理解>,不错.故转载之.

均以一个Form(java中为Frame)响应其中的Button对象的Click(java中为action)事件为例 

相同点是响应代码都是在Form中编码定义的

C#--事件函数回调机制,用delegate(类似指针)挂接事件的回调函数,三层--(事件源button,代理EventHandler,响应方法Form1)

在System的namespace中必定有这么一个delegate类型定义

public delegate void EventHandler(object source,EventArgs args);
//它定义了所有的事件响应的回调函数的基本声明类型
//source表示事件源对象--这里是button
//args表示事件的附加信息--由触发事件的button收集并赋值所以可以设想Button类的构造public class Button
public class Button
{
    public event EventHandler Click;          //定义单击事件
    public event EventHandler DoubleClick;    //定义双击事件

    //当单击事件发生时,系统则调用这个函数来对挂接在Click事件delegate响应链上的所有回调方法
    //protected virtual是为了方便子类覆写
    protected virtual void OnClick(EventArgs e)        
     {
        if(Click != null)    //判断挂接的事件回调函数不为空
         {
             Click(this,e);
         }
     }

    protected virtual void OnDoubleClick(EventArgs e)        
     {
        if(DoubleClick != null)
         {
             DoubleClick(this,e);
         }
     }
}这样作的意义在于,Form1实例化后作为Application的主线程运行,同时监听消息队列
当发生单击btnTest实例事件发生时,Form1所代表的那个Window的消息队列则调用btnTest的OnClick()方法,
并把一些事件信息当参数传进去
而OnClick方法反过来调用在Window的Form1对象内定义的btnTest_Click方法(.net中采用delegate实现,而win32中则使用函数指针!)
来触发响应代码!其中event关键字和+=/-=操作符受编译器的特别支持
编译时会自动展开成对应属性和方法
event属性支持add和remove关键字来代替get和set
java--observer模式,两层(listener监听者/performer事件源)系统有这么一个接口
java.awt.event.ActionListener类似于EventHandler专门用来定义单击事件的监听者(响应方法)类型
其中有两个很重要的方法:一个就是notify一个是actionPerformed(响应单击事件的函数定义)
者两个函数都是在事件发生时由事件源对象来调用的
而java.awt.event.ActionEvent则类似于EventArgs专门放置一些事件的附加信息如C#一般在一个Frame里面定义一个Button
public class MainFrame extends JFrame 
{
    private JButton jbtnShow = new JButton;
}

想让Frame响应Button的单击事件
可以有两种方法
一个是在Frame中调用

jbtnShow.addActionListener(new java.awt.event.ActionListener() 

    public void actionPerformed java.awt.event.ActionEvent e) 
     {
        //your perform code here
     };
}在方法参数中直接创建一个新的监听对象(内嵌对象)让这个对象实现actionPerformed方法,在其中写上MainFrame要响应的操作
因为是内联对象,所以MainFrame中的所有资源都是可达的

这种方法并不是Observer模式的标准实现

btw:java允许直接匿名实例化一个接口--这一点让我觉得很诡异,是灵活还是不守规矩,还是让大牛们来评判吧...
另一个方法则是observer模式的标准实现,即让MainFrame实现java.awt.event.ActionListener接口
也就意味着必须在MainFrame中实现actionPerformed方法作为响应Button单击事件的操作代码然后同样调用jbtnShow.addActionListener(this);
把自己挂接到Button的响应监听者链上如果要把自己从事件响应列中分离出来
可以调用jbtnShow.removeActionListener(this);Button的监听者链往往可以由一个Vector[]数组容器来担当无论那一种实现事件响应方式
当Button作为事件源发生单击事件时
触发了Button中的protected void OnAction(java.awt.event.ActionEvent e)方法(猜测有这么一个方法)
其实现猜测为
protected void OnAction(java.awt.event.ActionEvent e)
{
//其中遍历事件监听者的挂接数组Vector[]
//利用接口的多态性质调用各自实现的actionPerform(e)方法并把事件信息e当参数传进去
//这样也有一种回调的味道
//window消息机制调用Button的这个事件方法,这个方法再依次通知(调用)事件监听者链上的所有监听对象的响应方法代码
//和c#不同的是监听者链上挂接的是监听者对象,而不是delegate的回调函数handler指针
}调用方式一更像是C#的实现的java翻版了(也搞成三层的了,虽然中间那个listener是匿名实现的)
多亏了java有匿名对象/方法这么个好东西
可惜这个特性.net 2.0也开始支持了
如果变态一点用C#也通过实现observer模式来实现事件响应也是一件挺容易的事情

public interface EventListener    //事件监听者(响应者)实现--form
{
    void Performed(EventArgs args);
}

public interface EventObject    //事件源对象实现--button
{
    void AddListener(EventListener listener);
    void RemoveListener(EventListener listener);
}
然后响应者再把自己用eventObject.AddListener(this)挂载到响应链上就ok了
但是有了delegate还要写个ArrayList的事件监听者的handler容器又有多大意义呢?
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值