1、气象监测应用,错误示范

有一个气象站,分别有三个装置:温度感应装置,湿度感应装置,气压感应装置。WeathData对象跟踪气象站数据,WeathData有MeasurmentsChanged()方法,当感应装置数据变化后就会调用MeasurmentsChanged。目前需求是要三个布告板,分别是气象数据状况(CurrentConditionDisply),气象统计(StaisticsDisply),天气预报(ForcastDisply)用来显示各种的数据。按照这个需求我们可以设计出如下方式

  1. public class WeatherData(){
  2. private float Temperature{get;set;}
  3. private float Humidity{get;set;}
  4. private float Pressure{get;set;}
  5.  
  6. public void MeasurmentsChanged(){
  7. CurrentConditionDisply.Update(Temperature,Humidity,Pressure);
  8. StaisticsDisply.Update(Temperature,Humidity,Pressure);
  9. ForcastDisply.Update(Temperature,Humidity,Pressure);
  10. }
  11. }
  12.  
  13. public class CurrentConditionDisply{
  14. public void Update(float temperature,float humidity,float Pressure){
  15. //更新公布数据
  16. }
  17. }
  18. public class StaisticsDisply{
  19. public void Update(float temperature,float humidity,float Pressure){
  20. //更新统计数据
  21. }
  22. }
  23. public class ForcastDisply{
  24. public void Update(float temperature,float humidity,float Pressure){
  25. //更新天气预报
  26. }
  27. }

按照如上设计也能实现目前需求,但是如果新加入一种布告板或者删除一个布告板,那么我们需要去求改MeasurmentsChanged方法。

此例子带来的问题:

1、我们是针对实现编程,而非争对接口。

2、对于每个新的布告板,我们都得修改代码。

3、无法在运行是动态地增加或者删除布告板。

4、未封装改变的部分,违反了对修改关闭,对扩展开放。

2、使用观察者模式解耦

观察者模式:定义了对象之间的一对多依赖,当一个对象改变时,他的所有依赖都会收到通知并自动更新。

订阅报纸就是典型的观察者模式,出版社即为主题(subject),订阅者即是观察者(observer),当有新报纸时,报社就会派人送新报纸到订阅了该报纸的读者手上。这里先给出订阅模式类图,然后我们再对之前的气象站进行观察者模式封装。

3、利用观察者模式改进气象站

按照观察者模式进行设计和改进气象站代码并测试

  1. /// <summary>
  2. /// 主题
  3. /// </summary>
  4. public interface Subject
  5. {
  6. public void RegisterObserver(Observer o);
  7. public void RemoveObserver(Observer o);
  8. public void NotifyObserver();
  9. }
  10. /// <summary>
  11. /// 具体主题(气象站)
  12. /// </summary>
  13. public class WeatherData : Subject
  14. {
  15. private List<Observer> observers;
  16. private float Temperature { get; set; }
  17. private float Humidity { get; set; }
  18. private float Pressure { get; set; }
  19.  
  20. public WeatherData()
  21. {
  22. observers = new List<Observer>();
  23. }
  24. public void RegisterObserver(Observer o)
  25. {
  26. observers.Add(o);
  27. }
  28.  
  29. public void RemoveObserver(Observer o)
  30. {
  31. observers.Remove(o);
  32. }
  33.  
  34. //通知观察者
  35. public void NotifyObserver()
  36. {
  37. foreach (var o in observers)
  38. {
  39. o.Update(Temperature, Humidity, Pressure);
  40. }
  41. }
  42.  
  43. public void MeasurmentsChanged()
  44. {
  45. NotifyObserver();
  46. }
  47.  
  48. //数据变化
  49. public void SetMeasurments(float temperature, float humidity, float pressure)
  50. {
  51. Temperature = temperature;
  52. Humidity = humidity;
  53. Pressure = pressure;
  54. MeasurmentsChanged();
  55. }
  56. }
  57.  
  58. /// <summary>
  59. /// 订阅者
  60. /// </summary>
  61. public interface Observer
  62. {
  63. void Update(float temperature, float humidity, float pressure);
  64. }
  65.  
  66. public class CurrentConditionDisply : Observer
  67. {
  68. private Subject weatherData;
  69. public CurrentConditionDisply(Subject weatherData)
  70. {
  71. this.weatherData = weatherData;
  72. weatherData.RegisterObserver(this);
  73. }
  74. public void Update(float temperature, float humidity, float pressure)
  75. {
  76. Console.WriteLine($"当前情况布告板:{temperature},{humidity},{pressure}");
  77. }
  78. }
  79. public class StaisticsDisply : Observer
  80. {
  81. private Subject weatherData;
  82. public StaisticsDisply(Subject weatherData)
  83. {
  84. this.weatherData = weatherData;
  85. weatherData.RegisterObserver(this);
  86. }
  87. public void Update(float temperature, float humidity, float pressure)
  88. {
  89. Console.WriteLine($"统计数据布告板:{temperature},{humidity},{pressure}");
  90. }
  91. }
  92. public class ForcastDisply : Observer
  93. {
  94. private Subject weatherData;
  95. public ForcastDisply(Subject weatherData)
  96. {
  97. this.weatherData = weatherData;
  98. weatherData.RegisterObserver(this);
  99. }
  100. public void Update(float temperature, float humidity, float pressure)
  101. {
  102. Console.WriteLine($"天气预报布告板:{temperature},{humidity},{pressure}");
  103. }
  104. }

测试结果:

Head First设计模式——观察者模式的更多相关文章

  1. 18. 星际争霸之php设计模式--观察者模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  2. linkin大话设计模式--观察者模式

    linkin大话设计模式--观察者模式 观察者模式定义了对象间的一对多依赖关系,让一个或者多个观察者观察一个对象主题.当主题对象的状态发生改变的时候,系统能通知所有的依赖于此对象的观察者对象,从而能自 ...

  3. java设计模式--观察者模式(Observer)

    java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...

  4. js设计模式-观察者模式

    定义: 观察者模式又叫发布订阅模式,它定义了对象间的一种一对多的依赖关系.观察者模式让两个对象松耦合地联系在一起,虽然不太清楚彼此的细节,但这不影响他们之间的互相通信. 思路 定义一个对象,在对象中实 ...

  5. 【设计模式】Java设计模式 - 观察者模式

    [设计模式]Java设计模式 - 观察者模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 @一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长 ...

  6. [Head First设计模式]山西面馆中的设计模式——观察者模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 引言 不知不自觉又将设计模式融入生活了,吃个饭也不得安生,也发现生活中的很多场景,都可以用设计模式来模拟.原来设计模式就在 ...

  7. javascript 设计模式-----观察者模式

    观察者模式在设计模式中被重点提到,因为它应用的场景非常多,而且在模块化设计当中扮演着非常重要的角色.MVC模式中最底层的就是观察者模式,当下流行的javascript框架backbone就是很好地运用 ...

  8. c#设计模式-观察者模式

    Observer 与 Subject 互为耦合,但是这种耦合的双方都依赖于抽象,而不依赖于具体. 一.观察者模式 目的 我们都知道解决一个问题有N种解决方式,但在面向对象的设计中如何能做到“高内聚,低 ...

  9. JAVA 设计模式 观察者模式

    用途 观察者模式 (Observer) 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象. 这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 观 ...

  10. IOS设计模式-观察者模式

    前言:23种软件设计模式中的观察者模式,也是在软件开发中,挺常用的一种设计模式.而在苹果开发中,苹果Cocoa框架已经给我们实现了这个设 计模式,那就是通知和KVO(Key-Value Observi ...

随机推荐

  1. WPF 自定义UI控件学习

    最近项目中运用到了WPF处理三维软件,在C/S结构中WPF做UI还是有很多优越性,简单的学了一点WPF知识,成功的完成项目目标.项目过度阶段对于WPF的一些基本特点有了进一步了解 .至此花费一点时间研 ...

  2. C#中将表示颜色的string转换成Color

    场景 在Winform中需要存储某控件的Color属性,存储的是string字符串, 然后再对控件进行赋值时需要将string转换成Color. 实现 myPane.YAxis.Color = Sys ...

  3. 警告:stream not available

    1.修改mybatis.org//DTD Config 3.0//EN更改为mybatis.org//DTD//EN 2.将url换成http://mybatis.org/dtd/mybatis-3- ...

  4. hadoop snapshot 备份恢复 .

    1.允许创建快照 首先,在你想要进行备份的文件夹下面 执行命令,允许该文件夹创建快照 hdfs dfsadmin -allowSnapshot <path> 例如:hdfs dfsadmi ...

  5. graphics.drawRect()方法

    drawRect方法的官方API文档描述 drawRect public void drawRect(int x, int y, int width, int height) Draws the ou ...

  6. 松软带你学开发-SQLSELECTDISTINCT语句

    SQL SELECT DISTINCT 语句 在表中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值. 关键词 DISTINCT 用于返回唯一不同的值. 语法 ...

  7. 【linux】【gitlab】gitlab安装、备份、恢复、升级、内存消耗问题

    前言 GitLab:GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务.功能:Gitlab 是一个提供代码托管.提交审核和问题跟踪的代码管理平 ...

  8. 一次五分钟 angularJS (1)—— Binding

    引用angularjs 需要使用AngularJS,需要引用AngularJS的文件 ng-app 要将angular用到页面绑定的时候,我们需要指明它的作用域. 在上图中,ng-app=" ...

  9. Linux 部署vsftp服务及详解

    一.FTP服务概述: FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务. FTP(File Transf ...

  10. springboot + thymeleaf静态资源访问404

    在使用springboot 和thtmeleaf开发时引用静态资源404,静态资源结如下: index.html文件: <!DOCTYPE html> <html xmlns:th= ...