zoukankan      html  css  js  c++  java
  • 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}
    湿度:{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("=============================");
                }
            }
    }
  • 相关阅读:
    对java中接口的简单理解
    jqgrid
    sed跨行匹配替换
    linux 安装 mysql
    mysql 导入或导出(mysqldump)数据
    spring boot slf4j + logback
    原码、反码、补码
    Java线程池(一)
    springboot 多环境配置及打包资源
    springboot自定义yaml配置文件
  • 原文地址:https://www.cnblogs.com/chenyishi/p/13530026.html
Copyright © 2011-2022 走看看