说明:主要参考《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();
}

最新文章

  1. 【转】request.getServletPath()和request.getPathInfo()用法
  2. [转]Struts2工作原理
  3. 大家一起和snailren学java-(13)字符串
  4. Visual Studio 快速返回上次浏览/编辑的位置
  5. Js制作点击输入框时默认文字消失的效果
  6. 1103 POI2007 大都市meg
  7. 解决JDeveloper运行慢的设置/BPM/SOA Server JVM参数设定
  8. 【剑指offer】打印1到最大的n数字
  9. 洛谷-神奇的幻方-NOIP2015提高组复赛
  10. Linux下Hadoop2.7.1集群环境的搭建(超详细版)
  11. scrapy---callback 传递自定义参数
  12. 小dai浅谈通信网络(一)——引子
  13. 1. CMake 系列 - 从零构建动态库和静态库
  14. [Swift]LeetCode587. 安装栅栏 | Erect the Fence
  15. JDBC数据库连接池之dbcp
  16. jmeter之JDBC Request各种数据库配置
  17. HashSet中存放不重复元素
  18. [20171106]修改show spparameter的显示宽度.txt
  19. 踩过的坑:InteliIJ IDEA 打开的项目突然左侧目录结构消失了,如何处理?
  20. Docker技术入门与实战 第二版-学习笔记-9-Docker Compose 项目-1-举例说明

热门文章

  1. 硬核评测:企业上云的极速存储挑战,华为云全新极速IO云硬盘性能评测
  2. Reactive(3)5分钟理解 SpringBoot 响应式的核心-Reactor
  3. .Net Core的API网关Ocelot使用 (一)
  4. 纯css实现下雪特效
  5. [TimLinux] docker CentOS7安装docker-ce最新版
  6. Codeforces 题解 CF863A 【Quasi-palindrome】
  7. 使用@babel/preset-typescript取代awesome-typescript-loader和ts-loader
  8. JS基础-垃圾回收机制与内存泄漏的优化
  9. IDEA+Maven 整合SSM框架实现简单的增删改查(新手入门,傻瓜操作)
  10. 湖南大学第十四届ACM程序设计新生杯(重现赛)G a+b+c+d=? (16进制与LL范围)