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. FreeSql (三十)读写分离

    FreeSql 支持数据库读写分离,本功能是客户端的读写分离行为,数据库服务器该怎么配置仍然那样配置,不受本功能影响,为了方便描术后面讲到的[读写分离]都是指客户端的功能支持. 各种数据库的读写方案不 ...

  2. springboot数据库主从方案

    本篇分享数据库主从方案,案例采用springboot+mysql+mybatis演示:要想在代码中做主从选择,通常需要明白什么时候切换数据源,怎么切换数据源,下面以代码示例来做阐述: 搭建测试环境(1 ...

  3. Stanford公开课《编译原理》学习笔记(1~4课)

    目录 一. 编译的基本流程 二. Lexical Analysis(词法分析阶段) 2.1 Lexical Specification(分词原则) 2.2 Finite Automata (典型分词算 ...

  4. IO流——递归(输出所有文件)

    package pers.zbb.File; import java.io.File; public class FileDemo { public static void main(String[] ...

  5. 31 (OC)* 内存管理

    31 (OC)  内存管理 一:内存管理黄金法则. 如果对一个对象使用了alloc.[Mutable]copy,retain,那么你必须使用相应的realease或者autorelease 二:内存管 ...

  6. Webpack配置区分开发环境和生产环境

    在项目开发的时候,我们通常会将程序分为开发环境和生产环境(或者叫线上环境),开发环境通常指的是我们正在开发的这个阶段所需要的一些环境配置,也就是方便我们开发人员调试开发的一种环境:生产环境通常指的是我 ...

  7. 使用Fedora8 iso开发环境开发gtk3跨Linux多版本桌面应用

    原文: https://bbs.otherhill.com/index.php/topic/show/82 gtk3 demo在/usr/local/gtk3demo 目录下 cd /usr/loca ...

  8. Android [启动方式:standard singleTop singleTask singleInstance]

    栈顶Activity是当前正在显示的. 以A.B举例 1.standard 不同的Activity都存放在同一个栈中,每次创建实例都会堆放到栈顶,逐次返回直至退出. 创建实例B 创建实例A 点击返回时 ...

  9. Hadoop点滴-初识MapReduce(2)

    术语: job(作业):客户端需要执行的一个工作单元,包括输入数据.MP程序.配置信息 Hadoop将job分成若干task(任务)来执行,其中包括两类任务:map任务.reduce任务.这些任务在集 ...

  10. springboot 启动报错Consider defining a bean of type 'com.example.springbootdruid.mapper.UserMapper' in your configurati

    一.问题 springboot项目启动时报错: Field userMapper in com.example.springbootdruid.service.impl.UserServiceImpl ...