C#中使用委托和事件实现观察者模式(observer pattern)

来源:互联网 发布:电路仿真软件中文版 编辑:程序博客网 时间:2024/04/30 01:05

1.       Introduction:

观察者设计模式描述了一个可依赖(observable)对象和其它一些对象(observers)的关系。它也叫做Model/View模式,依赖模式或者是传播/监听模式。

下面给出的例子是父母和医生这两个观察者在孩子的状态每次更新时都能够收到讯息。

2.       Observer Design Pattern Structure:

    

3.       Class Diagram:

    

 我比较喜欢用Delegates/Events,所以我决定创建一个事件对象通过委托来通知每个观察者,事件所在的类为ObservableObject; ObservableObject应该允许添加或者移除观察者,每个观察者也是能够收到多个状态更新。

4.       实现代码:

ObservableObject是个抽象类,它里面的方法是用来和观察者交换。它允许客户端添加/移除观察者。而Notify()方法用来处理子类中的事件触发。

view plaincopy to clipboardprint?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace www.askbargains.com.ObserverDesignPatternLib  
  7. {  
  8.     public delegate void NotifyObserver(string key);  
  9.   
  10.     public abstract class ObservableObject  
  11.     {  
  12.         public event NotifyObserver NotifyObserverEvent;  
  13.   
  14.         public void AddObserver(NotifyObserver ob)  
  15.         {  
  16.             NotifyObserverEvent += ob;  
  17.         }  
  18.   
  19.         public void RemoveObserver(NotifyObserver ob)  
  20.         {  
  21.             NotifyObserverEvent -= ob;  
  22.         }  
  23.   
  24.         public void Notify(string kidName)  
  25.         {  
  26.             if (NotifyObserverEvent != null)  
  27.             {  
  28.                 NotifyObserverEvent(kidName);  
  29.             }  
  30.         }  
  31.     }  
  32. }  

 

     Kit类:

是ObservableObject类的子类,它也有自己的信息,比如status。每次DailyStatus属性被更新时,我们都会触发Notify事件。

view plaincopy to clipboardprint?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace www.askbargains.com.ObserverDesignPatternLib  
  7. {  
  8.     public class Kid : ObservableObject  
  9.     {  
  10.         public string Name { getset; }  
  11.   
  12.         private Status _dailyStatus;  
  13.   
  14.         public Status DailyStatus  
  15.         {  
  16.             get { return _dailyStatus; }  
  17.             set  
  18.             {  
  19.                 _dailyStatus = value;  
  20.                 Notify(this.Name);  
  21.             }  
  22.         }  
  23.     }  
  24. }  

 

Parent类和FamilyDoctor类:

我们创建parent类和familydoctor类作为我们的观察者。Parent类的DailyStatusUpdate()方法和FamilyDoctor类的ReceiveNotes()方法是两个update方法,它们是NotifyObserver委托的方法。

view plaincopy to clipboardprint?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace www.askbargains.com.ObserverDesignPatternLib  
  7. {  
  8.     public class Parent  
  9.     {  
  10.         private Dictionary<string, Kid> _kids = new Dictionary<string,>();  
  11.   
  12.         public Dictionary<string, Kid> Kids  
  13.         {  
  14.             get { return _kids; }  
  15.             set { _kids = value; }  
  16.         }  
  17.   
  18.         public void DailyStatusUpdate(string key)  
  19.         {  
  20.             Console.WriteLine("Parents received {0}'s daily status. " +   
  21.                               "updated on {1}, Notes: {2} ",   
  22.                               Kids[key].Name, Kids[key].DailyStatus.UpdatedOn,   
  23.                               Kids[key].DailyStatus.Description);  
  24.         }  
  25.     }  
  26. }  
  27.   
  28. using System;  
  29. using System.Collections.Generic;  
  30. using System.Linq;  
  31. using System.Text;  
  32.   
  33. namespace www.askbargains.com.ObserverDesignPatternLib  
  34. {  
  35.     public class FamilyDoctor  
  36.     {  
  37.         private Dictionary<string, Kid> _kids = new Dictionary<string,>();  
  38.   
  39.         public Dictionary<string, Kid> Patients  
  40.         {  
  41.             get { return _kids; }  
  42.             set { _kids = value; }  
  43.         }  
  44.   
  45.   
  46.         public void ReciveNotes(string patientName)  
  47.         {  
  48.             Console.WriteLine("Family Doctor received {0}'s new daily status. " +   
  49.                               "updates on: {1} . Notes:{2}",   
  50.                               Paitients[patientName].Name,   
  51.                               Paitients[patientName].DailyStatus.UpdatedOn,   
  52.                               Paitients[patientName].DailyStatus.Description);  
  53.         }  
  54.   
  55.     }  
  56. }  

 

最后是客户端的实现代码,这里使用控制台程序实现观察者模式,你可以通过任何其它方式来实现。

view plaincopy to clipboardprint?
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading;  
  6. using www.askbargains.com.ObserverDesignPatternLib;  
  7.   
  8. namespace www.askbargains.com.ObserverDesignPatternClient  
  9. {  
  10.     class Program  
  11.     {  
  12.         static void Main(string[] args)  
  13.         {  
  14.             //Two kids been created  
  15.             Kid kid1 = new Kid();  
  16.             Kid kid2 = new Kid();  
  17.   
  18.             kid1.Name = "Aimee";  
  19.             kid2.Name = "Elizabeth";  
  20.   
  21.             //one parent object created.   
  22.             //this parent has two kids in this case.   
  23.             Parent parent1 = new Parent();  
  24.             parent1.Kids.Add(kid1.Name, kid1);  
  25.             parent1.Kids.Add(kid2.Name, kid2);  
  26.   
  27.             //one family doctor object created  
  28.             //this doctor is kid2's family doctor,   
  29.             //and I am going to send the note when kid2 isn't well  
  30.             FamilyDoctor doc1 = new FamilyDoctor();  
  31.             doc1.Patients.Add(kid2.Name, kid2);  
  32.   
  33.             //I want to send notes to the parents.  
  34.             kid1.AddObserver(new NotifyObserver(parent1.DailyStatusUpdate));  
  35.             kid2.AddObserver(new NotifyObserver(parent1.DailyStatusUpdate));  
  36.   
  37.             //Update status for both Kids.   
  38.             //Parents will receive the notes at the same time  
  39.             kid1.DailyStatus = new Status(String.Format("{0} is happy", kid1.Name));  
  40.             kid2.DailyStatus = new Status(String.Format("{0} is fuzzy", kid2.Name));  
  41.   
  42.             //Updates the status after 5 secs  
  43.             Thread.Sleep(5000);  
  44.   
  45.             //after 5 secs, kid2 doesn't feel well. need to get doctor involved  
  46.             kid2.AddObserver(new NotifyObserver(doc1.ReciveNotes));  
  47.   
  48.             //update two kids' status.   
  49.             //Parent will recive two kids status  
  50.             //Doc1 start reciving kid2 's status  
  51.             kid1.DailyStatus = new Status(String.Format("{0} is happy", kid1.Name));  
  52.             kid2.DailyStatus = new Status(String.Format("{0} is sick. " +   
  53.                                           "Tempture : 39.7", kid2.Name));  
  54.   
  55.             //Updates the status after 5 secs  
  56.             Thread.Sleep(5000);  
  57.   
  58.             //update two kids' status  
  59.             kid1.DailyStatus = new Status(String.Format("{0} is happy", kid1.Name));  
  60.             kid2.DailyStatus = new Status(String.Format("{0} is back to normal. " +   
  61.                                           "she is happy now", kid2.Name));  
  62.   
  63.   
  64.             //Updates the status after 5 secs  
  65.             Thread.Sleep(5000);  
  66.   
  67.   
  68.             //since kid2 is fine. I am going to deattach the doc1's observation  
  69.             kid2.RemoveObserver(new NotifyObserver(doc1.ReciveNotes));  
  70.   
  71.             //update two kids' status  
  72.             kid1.DailyStatus = new Status(String.Format("{0} is happy. " +   
  73.                                    "Just had a big lunch", kid1.Name));  
  74.             kid2.DailyStatus = new Status(String.Format("{0} is happy. " +   
  75.                                    "Playing with her best friend Kevin", kid2.Name));  
  76.   
  77.             Console.WriteLine("Daily Report End!");  
  78.             Console.Read();  
  79.         }  
  80.     }  
  81. }  

 

结果展现:

 

转载自:http://blog.csdn.net/dujingjing1230/archive/2009/08/12/4438348.aspx

 

作者:dujingjing1230

原创粉丝点击