c# 实现观察者模式

 更新时间:2021年01月07日 16:54:28   作者:xhubobo  
这篇文章主要介绍了c# 实现观察者模式的步骤,帮助大家更好的理解和使用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# 实现观察者模式的详细内容,更多关于c# 观察者模式的资料请关注脚本之家其它相关文章!

相关文章

  • C#身份证验证小例子

    C#身份证验证小例子

    C#身份证验证小例子,需要的朋友可以参考一下
    2013-04-04
  • C#实现拆分合并Word表格中的单元格

    C#实现拆分合并Word表格中的单元格

    我们在使用Word制作表格时,由于表格较为复杂,只是简单的插入行、列并不能满足我们的需要。要做一个完整的表格,很多时候需要将单元格进行拆分或者合并。本文将详细为您介绍在Word表格中拆分或合并单元格的思路及方法,希望对大家有所帮助
    2022-12-12
  • C#实现只运行单个实例应用程序的方法(使用VB.Net的IsSingleInstance)

    C#实现只运行单个实例应用程序的方法(使用VB.Net的IsSingleInstance)

    这篇文章主要介绍了C#实现只运行单个实例应用程序的方法,本文使用的是VB.Net的IsSingleInstance方法实现,优于Mutex 和 Process 这两种只运行单个应用程序实例的方法,需要的朋友可以参考下
    2014-07-07
  • C#中的委托delegate用法的示例详解

    C#中的委托delegate用法的示例详解

    这篇文章主要介绍了C#中的委托用法的示例详解。本章将由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.NET Framework 中的委托和事件、委托中方法异常和超时的处理、委托与异步编程、委托和事件对Observer 设计模式的意义。感兴趣的可以了解一下
    2020-07-07
  • C# 表达式目录树Expression的实现

    C# 表达式目录树Expression的实现

    本文主要介绍了C# 表达式目录树Expression的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • C#执行js动态编译的方法

    C#执行js动态编译的方法

    这篇文章主要介绍了C#执行js动态编译的方法,是涉及动态编译脚本非常实用的技巧,需要的朋友可以参考下
    2015-01-01
  • Unity3D开发实战之五子棋游戏

    Unity3D开发实战之五子棋游戏

    这篇文章主要为大家详细介绍了Unity3D开发实战之五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09
  • C#使用反射和LINQ查询程序集的元数据

    C#使用反射和LINQ查询程序集的元数据

    在 C# 中,反射是一个强大的工具,它允许我们在运行时检查程序集、类型、方法等的元数据,结合 LINQ,我们可以用更简洁和表达力强的方式处理这些信息,本文将详细讲解如何使用反射与 LINQ 查询程序集的元数据,需要的朋友可以参考下
    2024-08-08
  • 利用C#实现进程管理器

    利用C#实现进程管理器

    这篇文章主要为大家详细介绍了如何利用C#实现自己的进程管理器,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以了解一下
    2022-12-12
  • unity 如何修改材质属性和更换shader

    unity 如何修改材质属性和更换shader

    这篇文章主要介绍了unity 修改材质属性和更换shader的操作方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04

最新评论