在前面的一篇文章中我讲到,delegate,event这些机制的实现本质上和observer pattern有很强的联系。那么他们的联系是怎么体现出来的呢?今天再次看了下《CLR via C#》这本书的时候,看到一个基于event的实例,通过和使用observer pattern的理解方式进行比较,我们应该能找到其中的联系了吧
书中讲到这样一个示例,加入我们要设计一个邮件应用,当收到一封邮件的时候,用户希望可以将消息转发给传真机或者寻呼机。从这一句话我们就嗅到了observer pattern的味道。基于observer pattern的话,我们完全可以提供一个完整的设计和实现。为了简单回顾一下Observer pattern的原理,我们作了一个如下的设计:
根据原来的文章,我们这里的几个要点如下:
1.IObserverable抽象类包含有一个IEmailObserver的List,提供给所有实现IEmailObserver接口的类来注册和注销,同时,EmailManager也通过这个List来调用所有实现IEmailObserver接口对象的ProcessEmail()方法。
2.根据书上的示例,当消息到来的时候,需要给接收端提供邮件的From, To和Subject等信息,我们可以将这些信息作为ProcessEmail方法的参数进行传递
之所以列出这两点,是因为要结合Observer pattern的特点和event实现的特点进行比较,具体针对observer pattern的实现就在此不赘述,可以参考前面关于此模式的文章。
如果按照书上使用event流程的话,系统交互的步骤如下:
1. 一个Fax对象注册MailManager的事件。
2.一个Pager对象注册MailManager的事件。
3.一个新的邮件消息到达MainManager.
4.MailManager对象通知所有注册的对象处理新的邮件消息。
天哪!看完这一部分之后,这个处理的过程居然和observer pattern的思路惊人的一致!
再看书上的第一步:定义一个类型用来包含其他的信息以发送给其他接收者
书中的代码如下:
Code
1internal class NewMailEventArgs : EventArgs
2{
3 private readonly String m_from, m_to, m_subject;
4
5 public NewMailEventArgs(String from, String to, String subject)
6 {
7 m_from = from; m_to = to; m_subject = subject;
8 }
9
10 public String From { get { return m_from; } }
11 public String To { get { return m_to; } }
12 public String Subject { get { return m_subject; } }
13}
这部分代码的目的纯粹就是定义一个可以传递相关消息给接收者的结构,在我们的设计中也可以定义一个包含From, To和Subject的Struct或者Class.
再看第2到第4步,分别是定义event member,定义方法OnNewMail然后构造一个方法调用OnNewMail。这些步骤都和我们的设计差不多。
相关的代码如下:
Code
1internal class MailManager
2{
3 public event EventHandler<NewMailEventArgs> NewMail;
4
5 // Step #3: Define a method responsible for raising the event
6 // to notify registered objects that the event has occurred
7 // If this class is sealed, make this method private and non-virtual
8 protected virtual void OnNewMail(NewMailEventArgs e)
9 {
10 EventHandler<NewMailEventArgs> temp = NewMail;
11
12 // If any objects registered interest with our event, notify them
13 if (temp != null) temp(this, e);
14 }
15
16 // Step #4: Define a method that translates the
17 // input into the desired event
18 public void SimulateNewMail(String from, String to, String subject)
19 {
20
21 // Construct an object to hold the information we wish
22 // to pass to the receivers of our notification
23 NewMailEventArgs e = new NewMailEventArgs(from, to, subject);
24
25 // Call our virtual method notifying our object that the event
26 // occurred. If no type overrides this method, our object will
27 // notify all the objects that registered interest in the event
28 OnNewMail(e);
29 }
30}
为了代码的简略,我删除了部分和线程安全相关的代码。通过比较我们可以看到,其实这些代码和我们设计的几乎每什么差别,除了使用event来声明和注册事件以外。
现在,再看看Event的实现,书上说到,当编译器碰到这么一行代码的时候:
public event EventHandler<NewMailEventArgs> NewMail = null;
它会将这行代码转换成如下的三个结构:
Code
1//1. A private delegate field that is initialized to null
2private EventHandler<NewMailEventArgs> NewMail = null;
3
4//2. A public add_xx method(where xx is the Event name)
5// Allows objects to register interest in the event
6[MethodImp(MethodImplOptions.Synchronized)]
7public void add_NewMail(EventHandler<NewMailEventArgs> value)
8{
9 NewMail = (EventHandler<NewMailEventArgs>)Delegate.Combine(NewMail, value);
10}
11
12//3. A public remove_xx method(where xx is the Event name)
13public void remove_NewMail(EventHandler<NewMailEventArgs> value)
14{
15 NewMail = (EventHandler<NewMailEventArgs>)Delegate.Remove(NewMail, value);
16}
17
看这些代码,不就是那些注册和注销接收者的代码么?
可见event的实现基本上就是一种observer pattern的实现,只是编译器在后面做了很多,把一些细节给隐藏起来了。