zoukankan      html  css  js  c++  java
  • 设计模式之观察者模式C#实现

    说明:主要参考《Head First设计模式(中文版)》,使用C#代码实现。

    代码:Github

    1、观察者模式UML图

    EA实现

    2、气象监测类图

    EA类图

    3、气象监测代码(书中C#版)

    3.1 Observer

    public interface IObserver
    {
        void Update(float temperature, float humidity, float pressure);
    }
    public interface IDisplayElement
    {
        void Display();
    }
    public class CurrentConditionDisplay : IObserver, IDisplayElement
    {
        private readonly ISubject _weatherData;
    
        private float _temperature;
        private float _humidity;
    
        public CurrentConditionDisplay(ISubject weatherData)
        {
            _weatherData = weatherData;
            _weatherData?.RegisterObserver(this);
        }
    
        public void Update(float temperature, float humidity, float pressure)
        {
            _temperature = temperature;
            _humidity = humidity;
            Display();
        }
    
        public void Display()
        {
            Console.WriteLine($"Current Conditions: {_temperature}F degress and {_humidity}% humidity");
        }
    }
    

    3.2 Subject

    public interface ISubject
    {
        void RegisterObserver(IObserver o);
        void RemoveObserver(IObserver o);
        void NotifyObservers();
    }
    public class WeatherData : ISubject
    {
        //观察者列表
        private readonly List<IObserver> _observerList;
    
        //天气数据
        private float _temperature;
        private float _humidity;
        private float _pressure;
    
        public WeatherData()
        {
            _observerList = new List<IObserver>();
        }
    
        /// <summary>
        /// 订阅观察者
        /// </summary>
        /// <param name="o">观察者对象</param>
        public void RegisterObserver(IObserver o)
        {
            _observerList.Add(o);
        }
    
        /// <summary>
        /// 移除观察者
        /// </summary>
        /// <param name="o">观察者对象</param>
        public void RemoveObserver(IObserver o)
        {
            if (_observerList.Contains(o))
            {
                _observerList.Remove(o);
            }
        }
    
        /// <summary>
        /// 发布数据
        /// </summary>
        public void NotifyObservers()
        {
            foreach (var observer in _observerList)
            {
                observer.Update(_temperature, _humidity, _pressure);
            }
        }
    
        /// <summary>
        /// 数据发生改变
        /// </summary>
        private void MeasurementChanged()
        {
            NotifyObservers();
        }
    
        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="temperature">温度</param>
        /// <param name="humidity">湿度</param>
        /// <param name="pressure">气压</param>
        public void SetMeasurements(float temperature, float humidity, float pressure)
        {
            _temperature = temperature;
            _humidity = humidity;
            _pressure = pressure;
            MeasurementChanged();
        }
    }
    

    3.3 测试代码

    private static void TestWeatherData()
    {
        var weatherData = new WeatherData();
        var currentConditionDisplay = new CurrentConditionDisplay(weatherData);
    
        weatherData.SetMeasurements(80, 65, 30.4f);
        weatherData.SetMeasurements(82, 70, 29.2f);
        weatherData.SetMeasurements(78, 90, 29.2f);
    }

    4、使用C#中IObservable接口实现气象监测

    4.1 辅助类/结构体

    public struct WeatherMessage
    {
        public float Temperature { get; set; }
        public float Humidity { get; set; }
        public float Pressure { get; set; }
    }
    
    public class MessageUnknownException : Exception
    {
        internal MessageUnknownException()
        {
    
        }
    }
    

    4.2 IObserver具体实现

    class CurrentConditionDisplayX : IObserver<WeatherMessage>, IDisplayElement
    {
        private IDisposable _unsubscribe;
    
        private float _temperature;
        private float _humidity;
    
        public void Subscribe(IObservable<WeatherMessage> provider)
        {
            if (provider != null)
            {
                _unsubscribe = provider.Subscribe(this);
            }
        }
    
        public void Unsubscribe()
        {
            _unsubscribe?.Dispose();
            _unsubscribe = null;
        }
    
        public void OnCompleted()
        {
            Console.WriteLine("CurrentConditionDisplayX: OnCompleted");
            Unsubscribe();
        }
    
        public void OnError(Exception error)
        {
            Console.WriteLine("CurrentConditionDisplayX: OnError");
        }
    
        public void OnNext(WeatherMessage value)
        {
            _temperature = value.Temperature;
            _humidity = value.Humidity;
            Display();
        }
    
        public void Display()
        {
            Console.WriteLine($"Current Conditions: {_temperature}F degress and {_humidity}% humidity");
        }
    }
    

    4.3 IObservable具体实现

    public class WeatherDataX : IObservable<WeatherMessage>
    {
        private readonly List<IObserver<WeatherMessage>> _observerList;
    
        public WeatherDataX()
        {
            _observerList = new List<IObserver<WeatherMessage>>();
        }
    
        /// <summary>
        /// 通知提供程序:某观察程序将要接收通知。
        /// </summary>
        /// <param name="observer">要接收通知的对象。</param>
        /// <returns>使资源释放的观察程序的接口。</returns>
        public IDisposable Subscribe(IObserver<WeatherMessage> observer)
        {
            if(!_observerList.Contains(observer))
            {
                _observerList.Add(observer);
            }
            return new Unsubcriber(_observerList, observer);
        }
    
        public void SetMeasurements(Nullable<WeatherMessage> message)
        {
            foreach (var observer in _observerList)
            {
                if (!message.HasValue)
                {
                    observer.OnError(new MessageUnknownException());
                }
                else
                {
                    observer.OnNext(message.Value);
                }
            }
        }
    
        public void EndTransmission()
        {
            foreach (var observer in _observerList.ToArray())
            {
                if (_observerList.Contains(observer))
                {
                    observer.OnCompleted();
                }
            }
            _observerList.Clear();
        }
    
        private class Unsubcriber : IDisposable
        {
            private List<IObserver<WeatherMessage>> _observerList;
            private IObserver<WeatherMessage> _observer;
    
            public Unsubcriber(List<IObserver<WeatherMessage>> observerList, IObserver<WeatherMessage> observer)
            {
                _observerList = observerList;
                _observer = observer;
            }
    
            public void Dispose()
            {
                if (_observerList != null && _observerList.Contains(_observer))
                {
                    _observerList.Remove(_observer);
                }
            }
        }
    }
    

    4.4 测试代码

    private static void TestWeatherDataX()
    {
        var weatherData = new WeatherDataX();
        var currentConditionDisplay = new CurrentConditionDisplayX();
    
        currentConditionDisplay.Subscribe(weatherData);
    
        weatherData.SetMeasurements(new WeatherMessage()
        {
            Temperature = 80,
            Humidity = 65,
            Pressure = 30.4f
        });
        weatherData.SetMeasurements(new WeatherMessage()
        {
            Temperature = 82,
            Humidity = 70,
            Pressure = 29.2f
        });
        weatherData.SetMeasurements(new WeatherMessage()
        {
            Temperature = 78,
            Humidity = 90,
            Pressure = 29.2f
        });
        weatherData.EndTransmission();
    }
  • 相关阅读:
    函数式编程二 之异常处理
    ANSI是什么编码?
    Python:解析PDF文本及表格——pdfminer、tabula、pdfplumber 的用法及对比
    文件(csv、excel、xml、html)的读取(read)和写入(write)方法——python
    [python]提取PPT中的文字(包括图片中的文字)
    spring boot druid数据源配置
    spring boot打包
    rust常用技巧
    01_spring概述
    spring boot集成swagger文档
  • 原文地址:https://www.cnblogs.com/xhubobo/p/11886301.html
Copyright © 2011-2022 走看看