c# 实现观察者模式

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

代码:Github

1、观察者模式UML图

2、气象监测类图

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();

}

以上是 c# 实现观察者模式 的全部内容, 来源链接: utcz.com/z/322985.html

回到顶部