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

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

public class WeatherData(){
    private float Temperature{get;set;}
    private float Humidity{get;set;}
    private float Pressure{get;set;}

    public void MeasurmentsChanged(){
        CurrentConditionDisply.Update(Temperature,Humidity,Pressure);
        StaisticsDisply.Update(Temperature,Humidity,Pressure);
        ForcastDisply.Update(Temperature,Humidity,Pressure);
    }
}

public class CurrentConditionDisply{
    public void Update(float temperature,float humidity,float Pressure){
        //更新公布数据
    }
}
public class StaisticsDisply{
    public void Update(float temperature,float humidity,float Pressure){
        //更新统计数据
    }
}
public class ForcastDisply{
    public void Update(float temperature,float humidity,float Pressure){
        //更新天气预报
    }
}

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

此例子带来的问题:

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

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

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

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

2、使用观察者模式解耦

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

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

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

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

    /// <summary>
    /// 主题
    /// </summary>
    public interface Subject
    {
        public void RegisterObserver(Observer o);
        public void RemoveObserver(Observer o);
        public void NotifyObserver();
    }
    /// <summary>
    /// 具体主题(气象站)
    /// </summary>
    public class WeatherData : Subject
    {
        private List<Observer> observers;
        private float Temperature { get; set; }
        private float Humidity { get; set; }
        private float Pressure { get; set; }

        public WeatherData()
        {
            observers = new List<Observer>();
        }
        public void RegisterObserver(Observer o)
        {
            observers.Add(o);
        }

        public void RemoveObserver(Observer o)
        {
            observers.Remove(o);
        }

        //通知观察者
        public void NotifyObserver()
        {
            foreach (var o in observers)
            {
                o.Update(Temperature, Humidity, Pressure);
            }
        }

        public void MeasurmentsChanged()
        {
            NotifyObserver();
        }

        //数据变化
        public void SetMeasurments(float temperature, float humidity, float pressure)
        {
            Temperature = temperature;
            Humidity = humidity;
            Pressure = pressure;
            MeasurmentsChanged();
        }
    }

    /// <summary>
    /// 订阅者
    /// </summary>
    public interface Observer
    {
        void Update(float temperature, float humidity, float pressure);
    }

    public class CurrentConditionDisply : Observer
    {
        private Subject weatherData;
        public CurrentConditionDisply(Subject weatherData)
        {
            this.weatherData = weatherData;
            weatherData.RegisterObserver(this);
        }
        public void Update(float temperature, float humidity, float pressure)
        {
            Console.WriteLine($"当前情况布告板:{temperature},{humidity},{pressure}");
        }
    }
    public class StaisticsDisply : Observer
    {
        private Subject weatherData;
        public StaisticsDisply(Subject weatherData)
        {
            this.weatherData = weatherData;
            weatherData.RegisterObserver(this);
        }
        public void Update(float temperature, float humidity, float pressure)
        {
            Console.WriteLine($"统计数据布告板:{temperature},{humidity},{pressure}");
        }
    }
    public class ForcastDisply : Observer
    {
        private Subject weatherData;
        public ForcastDisply(Subject weatherData)
        {
            this.weatherData = weatherData;
            weatherData.RegisterObserver(this);
        }
        public void Update(float temperature, float humidity, float pressure)
        {
            Console.WriteLine($"天气预报布告板:{temperature},{humidity},{pressure}");
        }
    }

测试结果:

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. 洛谷 P1219八皇后

    把全部,在这251秒,赌上! ——<游戏人生zero> 题目:https://www.luogu.org/problem/P1219 八皇后是一道非常非常非常经典的深搜+回溯的题目. 这道 ...

  2. android中的后退键——onBackPressed()的使用

    转自:http://blog.sina.com.cn/s/blog_5085156c0101725e.html 很多网友不明白如何在Android平台上捕获Back键的事件,Back键是手机上的后退键 ...

  3. 分享一个 pycharm 专业版的永久使用方法

    刚开始接触Python,首先要解决的就是Python开发环境的搭建. 目前比较好用的Python开发工具是PyCharm,他有社区办和专业版两个版本,但是社区版支持有限,我们既然想好好学python, ...

  4. 从零开始入门 K8s| 阿里技术专家详解 K8s 核心概念

    作者| 阿里巴巴资深技术专家.CNCF 9个 TCO 之一 李响 一.什么是 Kubernetes Kubernetes,从官方网站上可以看到,它是一个工业级的容器编排平台.Kubernetes 这个 ...

  5. HTML定位——绝对定位和相对定位、固定定位

    1.绝对定位 绝对定位指的是通过规定HTML元素在水平和垂直方向上的位置来固定元素,基于绝对定位的元素不会占据空间. 绝对定位的位置声明是相对于已定位的并且包含关系最近的祖先元素.如果当前需要被定为的 ...

  6. String的优化 Stringbuffer和Stringbuilder

    string 上次说到string是最好衍生出来的一种字符类型,实现原理是由char[].我们知道数组一旦创建时不可更改的,所以每一次进行字符串的拼接都是在new一个新的字符串进行添加,这样的话对内存 ...

  7. [Algorithm] Heap & Priority queue

    这里只是简单的了解,具体内容详见推荐的原链接 注意堆和树的区别 堆就是优先级队列的实现形式 堆排序 排序过程 Ref: 排序算法之堆排序(Heapsort)解析 第一步(构造初始堆): {7, 5, ...

  8. Beescms_v4.0 sql注入漏洞分析

    Beescms_v4.0 sql注入漏洞分析 一.漏洞描述 Beescms v4.0由于后台登录验证码设计缺陷以及代码防护缺陷导致存在bypass全局防护的SQL注入. 二.漏洞环境搭建 1.官方下载 ...

  9. Kubernetes的Secret对象的使用

    Secret可以想要访问的加密数据,存放到Etcd中,Pod可以通过的Volume的方式,访问到Secret保存的信息 ,当数据修改的时候,Pod挂载的Secret文件也会被修改 一.创建Secret ...

  10. 略学扩展Eculid算法

    扩展 Euclid 算法 Euclid 算法 辗转相除法 计算两个数最大公因数 \(\text{gcd}(a,\,b) = \text{gcd}(b,\,a\%b)\) exEuclid 算法 裴蜀定 ...