说明:主要参考《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#实现的更多相关文章

  1. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  2. 设计模式之观察者模式(Observable与Observer)

    设计模式之观察者模式(Observable与Observer) 好久没有写博客啦,之前看完了<设计模式之禅>也没有总结一下,现在回忆一下设计模式之观察者模式. 1.什么是观察者模式 简单情 ...

  3. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  4. php 设计模式之观察者模式(订阅者模式)

    php 设计模式之观察者模式 实例 没用设计模式的代码,这样的代码要是把最上面那部分也要符合要求加进来,就要修改代码,不符合宁增不改的原则 介绍 观察者模式定义对象的一对多依赖,这样一来,当一个对象改 ...

  5. [JS设计模式]:观察者模式(即发布-订阅者模式)(4)

    简介 观察者模式又叫发布---订阅模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知. 举一个现实生活中的例子,例如小 ...

  6. 实践GoF的23种设计模式:观察者模式

    摘要:当你需要监听某个状态的变更,且在状态变更时通知到监听者,用观察者模式吧. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:观察者模式>,作者: 元闰子 . 简介 现在有 ...

  7. java设计模式之观察者模式

    观察者模式 观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式.模型-视图(View)模式.源-收听者(Listener)模式或从属者模式)是软件设计模式的一种.在此种模 ...

  8. [python实现设计模式]-4.观察者模式-吃食啦!

    观察者模式是一个非常重要的设计模式. 我们先从一个故事引入. 工作日的每天5点左右,大燕同学都会给大家订饭. 然后7点左右,饭来了. 于是燕哥大吼一声,“饭来啦!”,5点钟定过饭的同学就会纷纷涌入餐厅 ...

  9. 【GOF23设计模式】观察者模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_观察者模式.广播机制.消息订阅.网络游戏对战原理 package com.test.observer; import ja ...

  10. 设计模式学习——观察者模式(Observer Pattern)

    0. 前言 观察者模式在许多地方都能够用到,特别是作为MVC模式的一部分,在MVC中,模型(M):存放数据,视图(V):显示数据.当模型中的数据发生改变时,视图会得到通知,这是典型的观察者模式. 1. ...

随机推荐

  1. pod install速度慢解决方案

    相信大家已经感受到pod install速度越来越慢了,网上提供了几种解决方案,但是都没有完全解决速度慢的问题. 使用国内镜像的Specs 在pod install时使用命令pod install - ...

  2. Unity3D 卡通描边之控制线条粗细

    一.前言 之前我发表过一篇Unity3D 卡通渲染 基于退化四边形的实时描边,最重要的实时描边已经实现了,本文接下来要完善一下它. 在之前的实时描边中,使用了几何着色器中的LineStream来进行绘 ...

  3. lerna式升级

    有段时间没更新博客了,是时候更新一波了. 之前不是vue-next出了吗,然后就去学习了一下,发现整个目录不是那么熟悉了,变成这样了: 于是就这个线索去研究了一下,发下这是用的 lerna + yar ...

  4. Centos7使用Yum安装高版本的LNMP

    [摘要] 本文旨在介绍使用yum的方式安装一些高版本的NGINX.MySQL.PHP服务.当然如果觉得红帽给的就够用,就用红帽给的就行. 在红帽系列的Linux操作系统中,nginx/mysql/ph ...

  5. Unity3D for iOS初级教程:Part 1/3(上)

    转自:http://www.cnblogs.com/alongu3d/archive/ 如果图片看不到,请查看原文 这篇教材是来自教程团队成员 Christine Abernathy, 他是Faceb ...

  6. 使用 webservice 实现 RPC 调用

    WebService 介绍 Web service 是一个平台独立的,低耦合的 web 的应用程序用于开发分布式的互操作的应用程序.Web Service 技术, 能使得运行在不同机器上的不同应用无须 ...

  7. csuoj-1900 锋芒毕露

    Description 小闪最近迷上了二刀流——不过他耍的其实是剑——新买了一个宝库用来专门存放自己收集的双剑.一对剑有两把,分只能左手用的和只能右手用的,各自有一个攻击力数值.虽然一对剑在小闪刚拿到 ...

  8. 10分钟搞定nginx实现负载均衡

    10.1 负载均衡的概念 对用户请求的数据进行调度的作用 对用户访问的请求网站可以进行压力的分担 10.2 常见的代理方式 10.2.1 正向代理 10.2.2 反向代理 10.3 负载均衡的部署环节 ...

  9. 【Python3网络爬虫开发实战】 分析Ajax爬取今日头条街拍美图

    前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理.作者:haoxuan10 本节中,我们以今日头条为例来尝试通过分析Ajax请求 ...

  10. ARTS-S golang定义类

    package main import "fmt" type Student struct { Num int64 Name string } func(s *Student) s ...