zoukankan      html  css  js  c++  java
  • 设计模式学习观察者模式

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

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

      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
  • 相关阅读:
    函数指针
    单链表的建立
    系统程序员成长计划组合的威力(三)
    通过XML构建TreeView
    关于Dll中导出string的问题
    关于类的拷贝构造函数、赋值构造函数探究
    系统程序员成长计划组合的威力(四)
    指纹识别软件安装包下载
    javaSE视频教程正式启动
    数组复习
  • 原文地址:https://www.cnblogs.com/kaysily/p/4590536.html
Copyright © 2011-2022 走看看