工具软件   办公软件   操作系统   网络安全   设计在线   程序开发   教程宝典   软件下载   软件论坛
您的位置:软件 > 开发者网络 > 微软开发专栏 > 技术专题 > 正文
探讨与比较Java和.NET的事件处理框架
[文章信息]
作者:
时间:2004-11-25
出处:程序员杂志
责任编辑:方舟
[文章导读]
事件驱动模型是软件系统平台中的一个重要区域
advertisement
热点推荐
· Java加密和数字签名编程快速入门
· 在VB6中用命令行为模式控制GUI动作
· Excel图表向导详解
· 浅析各种计算机病毒应对方法
· 2月16日软件精选 春节文章精彩回顾
[正文]

上一页  1 2 3  下一页

  事件的预订和发布

  Publisher必需能够接受多个subscribers的预订,所以在publisher当中必需维护预订者的列表以供将来发布事件使用。在Java语言的模式中,并没有提供特别的东西来帮助这件事,可以自己用collection 类来做,例如可以使用ArrayList 对象来做记录。Java的预订方法名的风格为addXXXListener(),因为在publisher端必需把subscriber 对象“添加”到预订者列表后面,如下图:


  对于subscriber来说,预订动作的内部处理是黑箱的,subscriber不用关心publisher是如何做预订记录的。参考以下代码片段:

class Publisher {
 private ArrayList listenerList = new ArrayList();
 public void addKeyListener(KeyListener l) {
  listenerList.add(l);
 }
 public void fireKeyPressedEvent(int keyCode) {
  Iterator iter = listenerList.iterator();
  while (iter.hasNext()) {
   KeyListener l = (KeyListener)iter.next();
   l.keyPressed(keyCode);
  }
 }
}

  当然这段代码只是简单的示意,如果要考虑多线程的安全问题,可能要在addKeyListener()前面加上synchronized;还有,有预订就必然相应的有“退订”(removeXXXListener()),在这里就不再把它写出来。

  如果每个publisher都要这样重复撰写这样的代码的确很麻烦。所以在.NET中势必希望能够提供一种用来帮助publisher记录预订者,和发布事件的工具。按一般设计者的初步想法,一定是先提供一个辅助类来协助:


  从语法上考虑简化,add/remove动作应该可以用C++的operator=()、operator+=()和operator-=()来完成。像这样:

Publisher publisher = new Publisher();
...
publisher.KeyEventHandlerDelegate += KeyPressedHandler;
//等同于
//publisher.EventHandlerDelegate.add(KeyPressedHandler);

  如果可以这样撰写的话,确实很简单。不过在强制性类型(strongly-typed)语言系统中,必需精确的定义add()方法参数中的delegate 类型,这样似乎无法写出一个可以公用的基础类。所以在.NET中,是结合delegate关键字,通过简单的语法,借助编译器来帮我们自动生成相关的代码。于是把delegate的能力再予以加强了:

Event type definition:
public delegate void KeyPressedDelegate(int keyCode);

Publisher:
class Publisher
{
 public KeyPressedDelegate KeyPressed;
 ...
 void FireKeyPressedEvent(int KeyCode)
 {
  if (KeyPressed != null)
   //依次调用记录在KeyPressed中的所有方法
   KeyPressed(keyCode);
 }
}

Subscriber:
void OnKeyPressed(int keyCode)
{
 ...
}
void OnKeyPressed2(int keyCode)
{
 ...
}
...
Publisher publisher = new Publisher();
publisher.KeyPressed = OnKeyPressed;  //预订
publisher.KeyPressed += OnKeyPressed2; //预订另一个

  这样一个delegate不仅可以帮忙记录一个以上的subscribers,也可以简单的通过一行的调用语句来发布事件。其实编译器会为每一个delegate 生成一个相应的类来帮助处理这些工作,不过是作为一个只是编写应用系统的程序员是不必要去了解这些细节的,有兴趣的人可以去研究System.Delegate和System.MulticastDelegate 类。

  上面看到的结果应该已经是比较满意的,但是仍有改善空间。首先,因为一个delegate成员是public的,任何人都可以任意的直接接触,有失面向对象世界中的信息封装和隐藏(information encapsulation and hiding)的原则。所以在C#中又增加一个关键字“event”,用在放在声明一个delegate成员变量的前面,这样表示只有在声明这个delegate的类内部才可以直接对它进行subscriber 调用。

public delegate void KeyPressedDelegate(int keyCode);
class Publisher
{
 public event KeyPressedDelegate KeyPressed;
 ...
 void FireKeyPressedEvent(int KeyCode)
 {
  if (KeyPressed != null)
   //只有在Publisher才可以
   KeyPressed(keyCode);
 }
}

// outside of Publisher...
Publisher publisher = new Publisher();
// !!! 不允许 !!! 会编译错误 !!!
publisher.KeyPressed(100);

  接着,event delegate是以一个成员变量的方式存在,如果能以属性的方式让外界进行存取,不是更好吗。于是又增加了event accessors。在C#语言中,是使用add和remove来封装实际的 += 和 -= 操作。如下:

class Publisher
{
 protected event KeyPressedDelegate m_KeyPressed;

 // event accessor。定义一个事件属性。
 public event KeyPressedDelegate KeyPressed
 {
  add
  {
   m_KeyPressed += value;
  }
  remove
  {
   m_KeyPressed -= value;
  }
 }
 void FireKeyPressedEvent(int KeyCode)
 {
  if (KeyPressed != null)
  m_KeyPressed(keyCode);
 }
}

  不管是事件变量或者是事件属性,对声明事件变量和属性的类的外部,只能对它做 += 和 -= 操作。这样可以加强它的安全性。当然event accessor只有add和remove操作,所以不管是任何人(包括声明该事件属性的类内部),也只能对事件属性做 += 和 -= 操作。
经过这样的改善,可以理论上更减弱publisher和subscriber之间的耦合力了。


上一页  1 2 3  下一页

天极社区邀请您:写博客日记  上传相片   论坛聊天  订阅电子杂志  推荐网摘   免费图铃工具
笔名:   请您注意:

 遵守国家有关法律、法规,尊重网上道德,承担一切因您的行为而直接或间接引起的法律责任。

 天极网拥有管理笔名和留言的一切权利。
评论:
 
发表评论推荐给朋友我想参加相关培训打印我对此感兴趣订阅电子杂志
相关内容焦点新闻
  • .NET框架和VS.NET中的SOAP
  • 五种常见的ASP.NET安全缺陷
  • ADO.NET2.0的十大新特性
  • 使用ADO.NET的最佳实践
  • .NET Web应用框架构建模式
  • 中兴携手阿尔卡特 全球逐鹿CDMA
  • 用友总裁王文京:誓将ERP变成“大众消费”
  • 香港消费者委员会:数码相机最贵未必最好
  • 外电称中兴正评估西门子手机业务 或能并购
  • 国信办督战八大行业灾难备份 将出台国家标准
  • 中国IT企业走进欧盟 搭第六框架计划直通车
  • 美邦银行用户注意 警惕新型“钓鱼”邮件
  • 微软三年时间磨出新IE 具有更强大安全性能
  • Advertisement