kaysily

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖着都会收到通知并自动更新。

 

设计原则 为了交互对象之间的松耦合设计而努力

 

  1 using System;
  2 using System.Collections;
  3 using System.Collections.Generic;
  4 using System.Linq;
  5 using System.Text;
  6 using System.Threading.Tasks;
  7 
  8 namespace ObserverPattern
  9 {
 10 
 11 //创建发送者的接口
 12     public interface IObserver
 13     {
 14         void update(float temp, float humidity, float pressure);
 15     }
 16 //主题接口,供注册和解除监听
 17     public interface ISubject
 18     {
 19         void registerObserver(IObserver o);
 20         void removeObserver(IObserver o);
 21         void notifyObserver();
 22     }
 23         //显示接口
 24     public interface IDisplayElement
 25     {
 26         void display();
 27     }
 28 
 29 //源,实现监听者的添加删除以及发送消息
 30     public class WeatherData : ISubject
 31     {
 32         public ArrayList observers;
 33         public float temperature;
 34         public float humidity;
 35         public float pressure;
 36 
 37 
 38         public WeatherData()
 39         {
 40             observers = new ArrayList();
 41         }
 42 
 43 
 44         public void registerObserver(IObserver o)
 45         {
 46             observers.Add(o);
 47         }
 48 
 49         public void removeObserver(IObserver o)
 50         {
 51             observers.Remove(o);
 52         }
 53 //给每个监听者发送消息
 54         public void notifyObserver()
 55         {
 56             for (int i = 0; i < observers.Count; i++)
 57             {
 58                 (observers[i] as IObserver).update(temperature, humidity, pressure);
 59             }
 60         }
 61 
 62 //触发消息
 63         public void measurementsChanged()
 64         {
 65             notifyObserver();
 66         }
 67 //设置消息值
 68         public void setMeasurements(float temperature, float humidity, float pressure)
 69         {
 70             this.temperature = temperature;
 71             this.humidity = humidity;
 72             this.pressure = pressure;
 73 
 74             measurementsChanged();
 75         }
 76 
 77     }
 78 
 79 //监听者之一
 80     public class CurrentConditionsDisplay : IObserver, IDisplayElement
 81     {
 82 
 83 
 84 
 85         public float temperature;
 86         public float humidity;
 87         public float pressure;
 88         private ISubject WeatherData;
 89         public CurrentConditionsDisplay(ISubject WeatherData)
 90         {
 91             this.WeatherData = WeatherData;
 92             WeatherData.registerObserver(this);//把自己注册进去监听
 93         }
 94 
 95 //weather会调用这个方法
 96         public void update(float temp, float humidity, float pressure)
 97         {
 98             this.temperature = temp;
 99             this.humidity = humidity;
100             this.pressure = pressure;
101             display();
102         }
103 //显示
104         public void display()
105         {
106             Console.WriteLine("Current conditions:" + temperature + "F degrees and " + humidity + "humidity");
107         }
108 
109 
110     }
111 }
View Code

 

 

微软提供的观察者模式:

发布源要实现 IObservable<T> 接口(定义基于推送的通知的提供程序)

 1     // 摘要: 
 2     //     定义基于推送的通知的提供程序。
 3     //
 4     // 类型参数: 
 5     //   T:
 6     //     提供通知信息的对象。
 7     public interface IObservable<out T>
 8     {
 9         // 摘要: 
10         //     通知提供程序:某观察程序将要接收通知。
11         //
12         // 参数: 
13         //   observer:
14         //     要接收通知的对象。
15         //
16         // 返回结果: 
17         //     对允许观察者在提供程序发送完通知前停止接收这些通知的接口的引用。
18         IDisposable Subscribe(IObserver<T> observer);
19     }

订阅者要实现 IObserver<in T>

 1   // 摘要: 
 2     //     提供用于接收基于推送的通知的机制。
 3     //
 4     // 类型参数: 
 5     //   T:
 6     //     提供通知信息的对象。
 7     public interface IObserver<in T>
 8     {
 9         // 摘要: 
10         //     通知观察者,提供程序已完成发送基于推送的通知。
11         void OnCompleted();
12         //
13         // 摘要: 
14         //     通知观察者,提供程序遇到错误情况。
15         //
16         // 参数: 
17         //   error:
18         //     一个提供有关错误的附加信息的对象。
19         void OnError(Exception error);
20         //
21         // 摘要: 
22         //     向观察者提供新数据。
23         //
24         // 参数: 
25         //   value:
26         //     当前的通知信息。
27         void OnNext(T value);
28     }

 

示例代码:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 
  7 namespace ObserverPattern
  8 {
  9     //坐标结构体
 10     public struct Location
 11     {
 12         double lat, lon;
 13 
 14         public Location(double latitude, double longitude)
 15         {
 16             this.lat = latitude;
 17             this.lon = longitude;
 18         }
 19 
 20         public double Latitude
 21         { get { return this.lat; } }
 22 
 23         public double Longitude
 24         { get { return this.lon; } }
 25     }
 26 
 27 
 28     
 29     /// <summary>
 30     /// 这是个订阅者
 31     /// </summary>
 32     public class LocationReporter : IObserver<Location>
 33     {
 34         private IDisposable unsubscriber;
 35         private string instName;
 36 
 37         public LocationReporter(string name)
 38         {
 39             this.instName = name;
 40         }
 41 
 42         public string Name
 43         { get { return this.instName; } }
 44         /// <summary>
 45         /// 订阅
 46         /// </summary>
 47         /// <param name="provider"></param>
 48         public virtual void Subscribe(IObservable<Location> provider)
 49         {
 50             if (provider != null)
 51                 unsubscriber = provider.Subscribe(this);
 52         }
 53         //     通知观察者,提供程序已完成发送基于推送的通知。
 54         public virtual void OnCompleted()
 55         {
 56             Console.WriteLine("The Location Tracker has completed transmitting data to {0}.", this.Name);
 57             this.Unsubscribe();
 58         }
 59         //     通知观察者,提供程序遇到错误情况。
 60         public virtual void OnError(Exception e)
 61         {
 62             Console.WriteLine("{0}: The location cannot be determined.", this.Name);
 63         }
 64         //     向观察者提供新数据。
 65         public virtual void OnNext(Location value)
 66         {
 67             Console.WriteLine("{2}: The current location is {0}, {1}", value.Latitude, value.Longitude, this.Name);
 68         }
 69         /// <summary>
 70         /// 解除订阅
 71         /// </summary>
 72         public virtual void Unsubscribe()
 73         {
 74             unsubscriber.Dispose();
 75         }
 76     }
 77 
 78     /// <summary>
 79     /// 源,实现推送消息的接口 IObservable<Location>
 80     /// </summary>
 81     public class LocationTracker : IObservable<Location>
 82     {
 83         /// <summary>
 84         /// 实例化一个通知列表
 85         /// </summary>
 86         public LocationTracker()
 87         {
 88             observers = new List<IObserver<Location>>();
 89         }
 90 
 91         private List<IObserver<Location>> observers;
 92         /// <summary>
 93         /// 新增订阅者
 94         /// </summary>
 95         /// <param name="observer">提供了实现接收者接口的实例</param>
 96         /// <returns></returns>
 97         public IDisposable Subscribe(IObserver<Location> observer)
 98         {
 99             if (!observers.Contains(observer))
100                 observers.Add(observer);
101             return new Unsubscriber(observers, observer);
102         }
103 
104         private class Unsubscriber : IDisposable
105         {
106             private List<IObserver<Location>> _observers;
107             private IObserver<Location> _observer;
108 
109             public Unsubscriber(List<IObserver<Location>> observers, IObserver<Location> observer)
110             {
111                 this._observers = observers;
112                 this._observer = observer;
113             }
114 
115             public void Dispose()
116             {
117                 if (_observer != null && _observers.Contains(_observer))
118                     _observers.Remove(_observer);
119             }
120         }
121         /// <summary>
122         /// 传送新的消息
123         /// </summary>
124         /// <param name="loc"></param>
125         public void TrackLocation(Nullable<Location> loc)
126         {
127             foreach (var observer in observers)
128             {
129                 if (!loc.HasValue)
130                     observer.OnError(new LocationUnknownException());
131                 else
132                     observer.OnNext(loc.Value);
133             }
134         }
135         /// <summary>
136         /// 通知观察者,消息已经发送完了
137         /// </summary>
138         public void EndTransmission()
139         {
140             foreach (var observer in observers.ToArray())
141                 if (observers.Contains(observer))
142                     observer.OnCompleted();
143 
144             observers.Clear();//清空订阅者
145         }
146     }
147     /// <summary>
148     /// 定义发生错误时处理方法
149     /// </summary>
150     public class LocationUnknownException : Exception
151     {
152         internal LocationUnknownException()
153         { }
154     }
155 }
View Code

调用:

 1             //实例化观察者1
 2             ObserverPattern.LocationReporter lreporter1 = new ObserverPattern.LocationReporter("Observer1");
 3             //实例化观察者2
 4             ObserverPattern.LocationReporter lreporter2 = new ObserverPattern.LocationReporter("Observer2");
 5             //实例化观察者3
 6             ObserverPattern.LocationReporter lreporter3 = new ObserverPattern.LocationReporter("Observer3");
 7             //发布源
 8             ObserverPattern.LocationTracker ltracker = new ObserverPattern.LocationTracker();
 9 
10             lreporter1.Subscribe(ltracker);//观察者1订阅了源
11             lreporter2.Subscribe(ltracker);//观察者2订阅了源
12             lreporter3.Subscribe(ltracker);//观察者3订阅了源
13             ltracker.TrackLocation(new ObserverPattern.Location(1, 2));//源发布消息,订阅者们都会收到消息
14             ltracker.TrackLocation(new ObserverPattern.Location(3, 32));
15             ltracker.TrackLocation(null);
16             ltracker.EndTransmission();//完成订阅,清空所有的订阅者
17 
18             ltracker.TrackLocation(new ObserverPattern.Location(1, 2));//这个时候将不会有任何人接收到消息了
19             Console.ReadLine();
View Code

 

posted on 2015-06-20 14:55  制造业程序员  阅读(242)  评论(0编辑  收藏  举报
sa?