!= null)
(*KeyPressedSink)(keyCode);//callback
}
}
Subscriber:
void KeyPressedHandler(int keyCode)
{
}
Publisher publisher = new Publisher();
//reGISter
publisher.KeyPressedSink = &KeyPressedHandler;
一个当代的纯面向对象程序语言,是肯定希望要把造成
程序复杂和不易维护的指针给去除的。所以在C#语言机制当中,势必要创造新的元素来取代,于是delegate(委托)出现了。如下:
Event type definition:
// 定义KeyPressedDelegate 为一个类似函数指针的类型,
// 该函数接受一个整数型参数,无返回值
delegate void KeyPressedDelegate(int keyCode);
Publisher:
class Publisher
{
public KeyPressedDelegate KeyPressed = null;
void FireEvent(int KeyCode)
{
if (KeyPressed != null)
KeyPressed(keyCode);
}
}
Subscriber:
void KeyPressedHandler(int keyCode)
{
}
Publisher publisher = new Publisher();
//register
publisher.KeyPressed = KeyPressedHandler;
一开始,你可以把KeyPressedDelegate当成是与函数指针相类似的东西,通过它你可以引用一个实例方法或静态方法,就好像引用一个对象一样。然后可以通过这个delegate直接调用其引用的方法。但是下面你会看到delegate更扩大了其引用能力。
事件的预订和发布
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
{
publ