C#IObservableとIObserverオブザーバーモード

13833 ワード

C#には、観察者モードを実現するためのIObservableインタフェースとIObserverインタフェースが提供する、IObservableはSubject(テーマ)インタフェースに相当するので、以下、代わりにどのように利用するかを説明する.Netフレームワークが提供するオブザーバーモードインタフェース.
 
WeatherDataクラスには気温,湿度,気圧などの属性が含まれる.
    class WeatherData
    {
        /// 
        ///   
        /// 
        public string temperature { get; set; }
        /// 
        ///   
        /// 
        public string humility { get; set; }
        /// 
        ///   
        /// 
        public string pressure { get; set; }
    }

 

WeatherDataPublisher类实现了IObservable接口,实现了Subscribe订阅方法。

    class WeatherDataPublisher : IObservable
    {
        List> observers = new List>();
        /// 
        ////// 
        /// 
        /// 
        public IDisposable Subscribe(IObserver observer)
        {
            observers.Add(observer);
            return new Unsubscribe(this.observers, observer);
        }
        /// 
        ///      
        /// 
        private class Unsubscribe : IDisposable
        {
            List> observers;
            IObserver observer;
            public Unsubscribe(List> observers
            , IObserver observer)
            {
                this.observer = observer;
                this.observers = observers;
            }

            public void Dispose()
            {
                if (this.observers != null)
                {
                    this.observers.Remove(observer);
                }
            }
        }
        /// 
        ///          
        /// 
        /// 
        private void Notify(WeatherData weatherData)
        {
            foreach (var observer in observers)
            {
                observer.OnNext(weatherData);
            }
        }
        /// 
        ///          
        /// 
        /// 
        public void ReciveNewData(WeatherData weatherData)
        {
            Notify(weatherData);
        }
    }

 

下面我们建立一个抽象类WeatherDisplayBase实现了IObserver接口,所有的天气展示板(观察者)继承这个抽象类,需实现OnNext方法,即接收到新数据推送后要进行的数据处理展示工作,并且可重写OnCompleted,OnError方法。

    abstract class WeatherDisplayBase : IObserver
    {
        public virtual void OnCompleted()
        {
        }
        public virtual void OnError(Exception error)
        {
        }
        public abstract void OnNext(WeatherData value);
    }

 
CurrentConditionDisplayクラスは現在の天気状況の展示板であり、WeatherDisplayBase抽象クラスを継承し、最新の天気データを展示する.
    class CurrentConditionDisplay : WeatherDisplayBase
    {
        public override void OnNext(WeatherData value)
        {
            Console.WriteLine("------------------");
            Console.WriteLine("       ");
            Console.WriteLine(string.Format("  :{0}
:{1}
:{2}
", value.temperature, value.humility, value.pressure)); } }

 
StatisticsConditionDisplay類は気温統計展示板であり、WeatherDisplayBase抽象類を継承し、過去最高温度、最低温度、平均温度を展示している.
    class StatisticsConditionDisplay : WeatherDisplayBase
    {
        List<float> temperatures = new List<float>();
        public override void OnNext(WeatherData value)
        {
            float temperature;
            if (float.TryParse(value.temperature, out temperature))
            {
                temperatures.Add(temperature);
            }
            Console.WriteLine("------------------");
            Console.WriteLine("     ");
            Console.WriteLine(string.Format("    :{0}
:{1}
:{2}
", temperatures.Average(), temperatures.Max(), temperatures.Min())); } }

 
使用方法
class Program
    {
        static void Main(string[] args)
        {
            WeatherDataPublisher publisher = new WeatherDataPublisher();
            CurrentConditionDisplay currentDisplay=new CurrentConditionDisplay();
            StatisticsConditionDisplay statisticsDisplay 
            = new StatisticsConditionDisplay();
            //         
            IDisposable currentDisplayUnsubscriber= 
            publisher.Subscribe(currentDisplay);
            //         
            IDisposable statisticsDisplayUnsubscriber = 
            publisher.Subscribe(statisticsDisplay);
             
            for (int i = 0; ; i++)
            {
                WeatherData weatherData = new WeatherData();
               Console.WriteLine("     ,  ,  ");
               string input = Console.ReadLine();
               var array= input.Split(',');
               weatherData.temperature = array[0];
               weatherData.humility = array[1];
               weatherData.pressure = array[2];
               Console.WriteLine("");
                //                   
               publisher.ReciveNewData(weatherData);
               Console.WriteLine("=============================");
            }
        }
}