首页 > 其他分享 >观察者模式

观察者模式

时间:2023-10-05 22:46:25浏览次数:26  
标签:temperature void float 观察者 模式 humidity pressure public

观察者模式

案例引入

要求

气象站案例要求

  • 1.气象站,可以将每天测量到的湿度,温度,气压等气象信息以公告的形式发布出去(发布到自己的网站或者第三方平台)。
  • 2.需要设计开发新的api,便于其他第三方也能接入气象站的数据。
  • 3.提供温度,气压,湿度的接口。
  • 4.策略的数据更新后,实时的通知第三方。

普通方案实现案例

通过对气象项目的分析,我们可以初步设计一个WeatherData类。有温度(temperature),湿度(humidity),气压(pressure)三个属性,还有dataChange方法。

  • 1.通过getXxx方法,可以让第三方接入,并得到相关信息。
  • 2.气象站定时的调用dataChange()去更新数据,在数据更新时,当第三方再次获取时,就能得到最新的数据,当然也可以推送数据,即定时的将数据,推送到目标网站上。
代码实现
/**
 * 1.核心类,包含最新的天气信息数据,可以推送给别人
 * 2.含有 private CurrentConditions currentConditions;
 * 3.数据更新时,主动调用currentConditions进行数据推送,这样接入方,就会及时看到最新数据
 *
 * @author 长名06
 * @version 1.0
 */
public class WeatherData {

    //温度
    private float temperature;
    //气压
    private float pressure;
    //湿度
    private float humidity;

    private CurrentConditions currentConditions;

    public WeatherData(CurrentConditions c) {
        this.currentConditions = c;
    }

    public float getTemperature() {
        return temperature;
    }

    public float getPressure() {
        return pressure;
    }

    public float getHumidity() {
        return humidity;
    }

    public void dataChange() {
        currentConditions.update(getTemperature(), getPressure(), getHumidity());
    }

    //当数据有更新时,就调用这个setData
    public void setData(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        //信息改变时,将最新信息,推送给接入方
        dataChange();
    }
}
/**
 * 显示今天天气情况,气象站自己的网站
 * @author 长名06
 * @version 1.0
 */
public class CurrentConditions {

    //温度
    private float temperature;
    //气压
    private float pressure;
    //湿度
    private float humidity;

    //更新数据 由WeatherData来调用,
    public void update(float temperature,float pressure,float humidity){
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }

    //展示数据
    public void display(){
        System.out.println("今天温度" + temperature);
        System.out.println("今天气压" + pressure);
        System.out.println("今天湿度" + humidity);
    }
}
/**
 * 观察者模式
 * @author 长名06
 * @version 1.0
 */
public class Client {
    public static void main(String[] args) {
        CurrentConditions currentConditions = new CurrentConditions();
        WeatherData weatherData = new WeatherData(currentConditions);


        weatherData.setData(30,100,25);
        System.out.println("=====天气变化=====");
        weatherData.setData(35,100,30);
    }
}
问题分析
  • 1.无法在运行时,动态的添加第三方。
  • 2.在WeatherData中,当增加一个第三方,都需要创建一个对应的第三方的公告板对象,并加入到dataChange,不利于维护,也不是动态加入。
  • 3.违反了ocp(开闭原则),=> 使用观察者模式。

观察者模式原理

观察者模式,类似订牛奶的业务,在观察者模式下,有以下角色,奶站/气象局(Subject),用户/第三方网站(Observer),Subject中有登记注册,移除和通知接口方法,register()注册,remove()移除,notify()通知注册用户,根据不同需求,不同实现,可以通知用户取数据,也可以推送给用户数据,也可以更新数据,Observer中接收输入,也就是修改数据的方法update()。
观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer数据变化,类似定牛奶的业务,Subject是1,Observer是多。

观察者模式实现案例

uml图

代码实现
/**
 * @author 长名06
 * @version 1.0
 */
public interface Subject {

    public void register(Observer o);

    public void remove(Observer o);

    public void notifies();

}
public interface Observer {

    public void update(float temperature,float pressure,float humidity);

}
/**
 *  1.核心类,包含最新的天气信息数据,可以推送给别人
 *  2.含有 观察者集合。使用ArrayList管理
 *  3.数据更新时,主动调用观察者集合进行数据推送,这样接入方,就会及时看到最新数据
 * @author 长名06
 * @version 1.0
 */
public class WeatherData implements Subject{

    //温度
    private float temperature;
    //气压
    private float pressure;
    //湿度
    private float humidity;

    private List<Observer> observers = new ArrayList<>();

    public float getTemperature() {
        return temperature;
    }

    public float getPressure() {
        return pressure;
    }

    public float getHumidity() {
        return humidity;
    }

    public void dataChange(){
        notifies();//通知所有注册用户
    }

    //当数据有更新时,就调用这个setData
    public void setData(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        //信息改变时,将最新信息,推送给接入方
        dataChange();
    }

    @Override
    public void register(Observer o) {
        observers.add(o);
    }

    @Override
    public void remove(Observer o) {
        if(observers.contains(o)) {
            observers.remove(o);
        }
    }

    @Override
    public void notifies() {
        for(Observer o : observers){
            o.update(this.temperature,this.pressure,this.humidity);
        }
    }
}
public class TenXun implements Observer{
    //温度
    private float temperature;
    //气压
    private float pressure;
    //湿度
    private float humidity;

    //更新数据 由WeatherData来调用,
    @Override
    public void update(float temperature,float pressure,float humidity){
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }

    //展示数据
    public void display(){
        System.out.println("====腾讯网站====");
        System.out.println("腾讯 今天温度" + temperature);
        System.out.println("腾讯 今天气压" + pressure);
        System.out.println("腾讯 今天湿度" + humidity);
    }
}
/**
 * @author 长名06
 * @version 1.0
 */
public class XingLang implements Observer{

    //温度
    private float temperature;
    //气压
    private float pressure;
    //湿度
    private float humidity;

    //更新数据 由WeatherData来调用,
    @Override
    public void update(float temperature,float pressure,float humidity){
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }

    //展示数据
    public void display(){
        System.out.println("====新浪网站====");
        System.out.println("新浪 今天温度" + temperature);
        System.out.println("新浪 今天气压" + pressure);
        System.out.println("新浪 今天湿度" + humidity);
    }
}
public class Baidu implements Observer {
    //温度
    private float temperature;
    //气压
    private float pressure;
    //湿度
    private float humidity;

    //更新数据 由WeatherData来调用,
    @Override
    public void update(float temperature,float pressure,float humidity){
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        display();
    }

    //展示数据
    public void display(){
        System.out.println("====百度网站====");
        System.out.println("百度 今天温度" + temperature);
        System.out.println("百度 今天气压" + pressure);
        System.out.println("百度 今天湿度" + humidity);
    }

}
/**
 * @author 长名06
 * @version 1.0
 */
public class Client {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();

        Baidu baidu = new Baidu();
        TenXun tenXun = new TenXun();
        XingLang xingLang = new XingLang();

        weatherData.register(baidu);
        weatherData.register(tenXun);
        weatherData.register(xingLang);

        weatherData.setData(20,100,30.3F);

        weatherData.remove(xingLang);

        System.out.println("====某个用户不订阅了====");
        weatherData.setData(20,100,30.3F);
    }
}
观察者模式优势

1.使用观察者模式后,以集合的形式来管理用户(Observer),包括注册,移除和通知。
2.这样我们增加观察者(可以理解为一个新的用户),就不需要取修改核心类,WeatherData不用修改代码,遵守了ocp。

观察者模式在JDK源码分析

1.JDK的ObServable类就使用了观察者模式。


2.角色分析
​ 2.1 Observable的作用和地位等价于我们前面讲过的Subject.
​ 2.2 Observable是类,不是接口,类中也实现了核心的方法,即管理Observable的方法,add,remove,notify等。
​ 2.3 Observer的作用和地位等价于我们前面讲过的Observer,有update。
​ 2.4 Observable和Observer的使用方法和前面讲过的一样,只是Observable是类,通过继承来实现观察者模式。
只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。

标签:temperature,void,float,观察者,模式,humidity,pressure,public
From: https://www.cnblogs.com/changming06/p/17744024.html

相关文章

  • Flutter/Dart第10天:Dart高级特性Pattern模式的全部类型(共15种)
    Dart官方文档:https://dart.dev/language/pattern-types重要说明:本博客基于Dart官网文档,但并不是简单的对官网进行翻译,在覆盖核心功能情况下,我会根据个人研发经验,加入自己的一些扩展问题和场景验证。和操作符一样,模式运算也遵循一定的优先级规则,我们可以通过增加括号()让低优先级......
  • go语言ent教程:开启debug调试模式
    背景:ent模式是没有开启debug模式的 开启ent的调试模式有2种方法:一、通过配置选项开启client,err:=ent.Open("mysql","root:dev@123456@tcp(localhost:3306)/test?parseTime=True",ent.Debug()) 二、客户端调用Debug函数iferr:=client.Schema.Crea......
  • 软件设计模式系列之二十五——访问者模式
    访问者模式(VisitorPattern)是一种强大的行为型设计模式,它允许你在不改变被访问对象的类的前提下,定义新的操作和行为。本文将详细介绍访问者模式,包括其定义、举例说明、结构、实现步骤、Java代码实现、典型应用场景、优缺点、类似模式以及最后的小结。1模式的定义访问者模式允许......
  • redis主从复制基础上搭建哨兵模式
    假如156和157是不同的两台服务器两台redis主从复制基础上搭建哨兵模式如下156redis.confmasterauth123456bind0.0.0.0requirement123456daemonizeyessentinel.confsentinelauth-passmymaster123456sentinelmonitormymaster10.190.107.15663792157......
  • 传统的MVC开发模式和前后端分离开发模式
    1.引言在当今互联网时代,移动应用和网页应用的发展极大地推动了前后端分离开发模式的兴起。传统的后端渲染方式已经不能满足用户对高性能和优质用户体验的需求,于是前后端分离逐渐成为了一种主流的开发模式。前后端分离开发模式通过将前端和后端的开发分离,极大地提高了开发效率和......
  • 软件设计模式系列之二十三——策略模式
    1模式的定义策略模式(StrategyPattern)是一种行为型设计模式,它允许在运行时动态选择算法的行为。这意味着你可以定义一系列算法,将它们封装成独立的策略对象,然后根据需要在不修改客户端代码的情况下切换这些算法。策略模式有助于解决问题领域中不同行为的变化和扩展,同时保持代码的......
  • MapReduce运行模式
    1、yarn集群运行先将之前写好的MapReduce程序进行打包--Maven-->package;打包完成之后的jar包在target目录下可以找到!!!之后将jar包上传到我们的虚拟机文件夹里面去;之后输入命令:hadoopjarjar包名称jar包主类的全路径名称回车之后开始运行;在hdfs的浏览器界面(9870)能够找到......
  • python多进程:fork模式和spawn模式
    python多进程:fork模式和spawn模式fork模式1.仅unix系统支持,并且是unix系统的默认模式.2.使用该模式创建子进程的时候,会复制父进程的全部变量,支持传参(任意类型)给子进程,但是不会复制父进程的线程.3.该模式相当于将父进程的内存复制一份用于创建子进程.但是由于不复制线程......
  • Flutter/Dart第09天:Dart高级特殊Pattern模式的概览和用法
    Dart官方文档:https://dart.dev/language/patterns重要说明:本博客基于Dart官网文档,但并不是简单的对官网进行翻译,在覆盖核心功能情况下,我会根据个人研发经验,加入自己的一些扩展问题和场景验证。Pattern模式匹配的定义官网定义:PatternsareasyntacticcategoryintheDartlan......
  • 为什么懒汉式单例模式要加volatile修饰符
    publicclassLazySingleton{privateLazySingleton(){}privatevolatilestaticLazySingletoninstance;publicsynchronizedstaticLazySingletongetInstance(){if(instance==null){instance=newLazySi......