发布者和订阅者
很多程序都有一个共同的需求,即当一个特定的程序事件发生时,程序的其他部分可以得到
该事件已经发生的通知。
发布者/订阅者模式(publisher/subscriber pattem)可以满足这种需求。在这种模式中,发布
者类定义了一系列程序的其他部分可能感兴趣的事件。其他类可以“注册",以便在这些事件发
生时收到发布者的通知。这些订阅者类通过向发布者提供一个方法来“注册"以获取通知。当事
件发生时,发布者“触发事件",然后执行订阅者提交的所有事件。
由订阅者提供的方法称为回调方法,因为发布者通过执行这些方法来“往回调用订阅者的方
法”。还可以将它们称为事件处理程序,因为它们是为处理事件而调用的代码。图15-1演示了这
个过程,展示了拥有一个事件的发布者以及该事件的三个订阅者。
下面是一些有关事件的重要事项。
- 发布者(publisher)发布某个事件的类或结构,其他类可以在该事件发生时得到通知。
- 订阅者(subscriber)注册并在事件发生时得到通知的类或结构。
- 事件处理程序(event)由订阅者注册到事件的方法,在发布者触发事件时执行。
事件处理程序方法可以定义在事件所在的类或结构中,也可以定义在不同的类或结构中。 - 触发(raise)事件调用(invoke)或触发(fire)事件的术语。当事件被触发时,所有
注册到它的方法都会被依次调用。
上一章介绍了委托。事件的很多部分都与委托类似。实际上,事件就像是专门用于某种特殊
用途的简单委托。委托和事件的行为之所以相似,是有充分理由的。事件包含了一个私有的委托,
如图15-2所示。
有关事件的私有委托需要了解的重要事项如下。
- 事件提供了对它的私有控制委托的结构化访问。也就是说,你无法直接访问委托。
- 事件中可用的操作比委托要少,对于事件我们只可以添加、删除或调用事件处理程序。
- 事件被触发时,它调用委托来依次调用调用列表中的方法。
注意,在图15-2中,只有+=和-=运算符在事件框的左边。这是因为它们是事件唯一允许的
操作(除了调用事件本身)。
图15-3演示了一个叫作lncrementer的类,它按照某种方式进行计数。 - lncrementer定义了一个CountedADozen事件,每次累积到12个项时将会触发该事件。
- 订阅者类Dozens和SomeOtherClass各有一个注册到CountedADozen事件的事件处理程序。
- 每当触发事件时,都会调用这些处理程序。