C# IObservable與IObserver觀察者模式


C#中提供了IObservable<T>接口和IObserver<T>接口來實現觀察者模式,IObservable<T>相當於Subject(主題)接口,下面我們就以代嗎來說明下如何利用.net框架提供的觀察者模式接口。

 

WeatherData類包含氣溫,濕度,氣壓等屬性。

    class WeatherData
    {
        /// <summary>
        /// 氣溫
        /// </summary>
        public string temperature { get; set; }
        /// <summary>
        /// 濕度
        /// </summary>
        public string humility { get; set; }
        /// <summary>
        /// 氣壓
        /// </summary>
        public string pressure { get; set; }
    }

 

WeatherDataPublisher類實現了IObservable接口,實現了Subscribe訂閱方法。

    class WeatherDataPublisher : IObservable<WeatherData>
    {
        List<IObserver<WeatherData>> observers = new List<IObserver<WeatherData>>();
        /// <summary>
        /// 訂閱主題,將觀察者添加到列表中
        /// </summary>
        /// <param name="observer"></param>
        /// <returns></returns>
        public IDisposable Subscribe(IObserver<WeatherData> observer)
        {
            observers.Add(observer);
            return new Unsubscribe(this.observers, observer);
        }
        /// <summary>
        /// 取消訂閱類
        /// </summary>
        private class Unsubscribe : IDisposable
        {
            List<IObserver<WeatherData>> observers;
            IObserver<WeatherData> observer;
            public Unsubscribe(List<IObserver<WeatherData>> observers
            , IObserver<WeatherData> observer)
            {
                this.observer = observer;
                this.observers = observers;
            }

            public void Dispose()
            {
                if (this.observers != null)
                {
                    this.observers.Remove(observer);
                }
            }
        }
        /// <summary>
        /// 通知已訂閱的觀察者
        /// </summary>
        /// <param name="weatherData"></param>
        private void Notify(WeatherData weatherData)
        {
            foreach (var observer in observers)
            {
                observer.OnNext(weatherData);
            }
        }
        /// <summary>
        /// 接收最新的天氣數據
        /// </summary>
        /// <param name="weatherData"></param>
        public void ReciveNewData(WeatherData weatherData)
        {
            Notify(weatherData);
        }
    }

 

下面我們建立一個抽象類WeatherDisplayBase實現了IObserver接口,所有的天氣展示板(觀察者)繼承這個抽象類,需實現OnNext方法,即接收到新數據推送后要進行的數據處理展示工作,並且可重寫OnCompleted,OnError方法。

    abstract class WeatherDisplayBase : IObserver<WeatherData>
    {
        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}\n濕度:{1}\n氣壓:{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}\n最高溫度:{1}\n最低溫度:{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("=============================");
            }
        }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM