你知道观察者模式吗?

本文介绍了观察者模式的概念,通过一个气象站的例子解释了其工作原理。接着展示了如何自定义实现观察者模式,包括主题类、观察者接口及其实现。然后,对比了Java内置的Observable和Observer接口的使用,同样实现了气象信息的发布和订阅。测试代码证实了两种实现的正确性。
摘要由CSDN通过智能技术生成

一、观察者模式

定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖着都会收到通知并自动更新。
举个例子,其实就是报纸订阅服务,出版者和订阅者的关系。出版者一旦有了新的报纸,就去通知订阅者“最新的报纸已经到了”,你可以这么理解。
出版者就是主题,订阅者就是观察者。

二、举例

设计一个气象站,要求如下

  • 气象站一旦接受到新的气象信息,就马上通知它的订阅者
  • 订阅者收到信息之后,马上将信息展示在布告板上

自定义观察者模式

主题类接口

package com.jackeys.ObserverMode.DIY;


/**
 * @Description: 主题类接口
 * @ClassName: Subject
 * @Package com.jackeys.ObserverMode
 * @Author: Jackeys 1623427047@qq.com
 * @Copyright 版权归Jackeys企业(或个人)所有
 * @CreateTime: 2021/10/6 11:48
 * @Version: 1.0
 */
public interface Subject {
    /**
     * 用来注册观察者
     * @param observer 观察者
     */
    void registerObserver(Observer observer);

    /**
     * 用来删除观察者
     * @param observer 观察者
     */
    void removeObserver(Observer observer);

    /**
     * 当主题改变时,通知所有观察者
     */
    void notifyObservers();
}

主题接口实现类

package com.jackeys.ObserverMode.DIY;


import java.util.ArrayList;

/**
 * @Description: 主题接口实现类
 * @ClassName: WeatherData
 * @Package com.jackeys.ObserverMode
 * @Author: Jackeys 1623427047@qq.com
 * @Copyright 版权归Jackeys企业(或个人)所有
 * @CreateTime: 2021/10/6 11:58
 * @Version: 1.0
 */
public class WeatherData implements Subject {

    private ArrayList<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData() {
        this.observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(Observer observer) {
        this.observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        int index = observers.indexOf(observer);
        if (index >= 0) {
            this.observers.remove(index);
        }
    }

    /**
     * 通知所有观察者
     */
    @Override
    public void notifyObservers() {
        for(int i=0;i<this.observers.size();i++){
            this.observers.get(i).update(this.temperature,this.humidity,this.pressure);
        }
    }

    /**
     * 温度改变,通知所有观察者
     */
    public void measurementsChanged(){
        this.notifyObservers();
    }

    /**
     * 放入气象数据,并通知温度改变
     * @param temperature 温度
     * @param humidity 湿度
     * @param pressure 气压
     */
    public void setMeasurements(float temperature,float humidity,float pressure){
        this.temperature=temperature;
        this.humidity=humidity;
        this.pressure=pressure;
        this.measurementsChanged();
    }
}

观察者接口

package com.jackeys.ObserverMode.DIY;

/**
 * @Description: 观察者类接口
 * @ClassName: Observer
 * @Package com.jackeys.ObserverMode
 * @Author: Jackeys 1623427047@qq.com
 * @Copyright 版权归Jackeys企业(或个人)所有
 * @CreateTime: 2021/10/6 11:49
 * @Version: 1.0
 */
public interface Observer {
    /**
     * 改变时,将数据传给所有的观察者
     * @param temp 温度
     * @param humidity 湿度
     * @param pressure 气压
     */
    void update(float temp,float humidity,float pressure);
}

观察者接口实现类

package com.jackeys.ObserverMode.DIY;

/**
 * @Description: 布告板类
 * @ClassName: CurrentConditionsDisplay
 * @Package com.jackeys.ObserverMode
 * @Author: Jackeys 1623427047@qq.com
 * @Copyright 版权归Jackeys企业(或个人)所有
 * @CreateTime: 2021/10/6 12:07
 * @Version: 1.0
 */
public class CurrentConditionsDisplay implements Observer, DisplayElement {
    private float temperature;
    private float humidity;
    private float pressure;
    private Subject weatherData;

    /**
     * 放入主题
     * @param weatherData
     */
    public CurrentConditionsDisplay(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }

    /**
     * 显示气象信息
     */
    @Override
    public void display() {
        System.out.println("现在的天气:温度 "+this.temperature+",湿度 "+this.humidity+",气压 "+this.pressure);
    }

    /**
     * 改变气象信息
     * @param temp 温度
     * @param humidity 湿度
     * @param pressure 气压
     */
    @Override
    public void update(float temp, float humidity, float pressure) {
        this.temperature=temp;
        this.humidity=humidity;
        this.pressure=pressure;
        this.display();
    }
}

布告板接口

package com.jackeys.ObserverMode.DIY;

/**
 * @Description: 显示类接口
 * @ClassName: DisplayElement
 * @Package com.jackeys.ObserverMode
 * @Author: Jackeys 1623427047@qq.com
 * @Copyright 版权归Jackeys企业(或个人)所有
 * @CreateTime: 2021/10/6 11:55
 * @Version: 1.0
 */
public interface DisplayElement {
    /**
     * 用来显示温度、湿度、气压
     */
    void display();
}

测试

package com.jackeys.ObserverMode.DIY;

/**
 * @Description: 测试观察者模式
 * @ClassName: Test
 * @Package com.jackeys.ObserverMode
 * @Author: Jackeys 1623427047@qq.com
 * @Copyright 版权归Jackeys企业(或个人)所有
 * @CreateTime: 2021/10/6 12:13
 * @Version: 1.0
 */
public class Test {
    public static void main(String[] args) {
        WeatherData weatherData=new WeatherData();
        CurrentConditionsDisplay currentConditionsDisplay=new CurrentConditionsDisplay(weatherData);
        CurrentConditionsDisplay currentConditionsDisplay1=new CurrentConditionsDisplay(weatherData);
        weatherData.setMeasurements(1.1f,1.2f,1.3f);
    }
}

输出
在这里插入图片描述

Java内置观察者模式

布告板接口

package com.jackeys.ObserverMode.JavaInner;

/**
 * @Description: 显示类接口
 * @ClassName: DisplayElement
 * @Package com.jackeys.ObserverMode
 * @Author: Jackeys 1623427047@qq.com
 * @Copyright 版权归Jackeys企业(或个人)所有
 * @CreateTime: 2021/10/6 11:55
 * @Version: 1.0
 */
public interface DisplayElement {
    /**
     * 用来显示温度、湿度、气压
     */
    void display();
}

主题类

package com.jackeys.ObserverMode.JavaInner;

import java.util.Observable;

/**
 * @Description: 主题类
 * @ClassName: WeatherData
 * @Package com.jackeys.ObserverMode.JavaInner
 * @Author: Jackeys 1623427047@qq.com
 * @Copyright 版权归Jackeys企业(或个人)所有
 * @CreateTime: 2021/10/6 13:02
 * @Version: 1.0
 */
public class WeatherData extends Observable {

    private float temperature;
    private float humidity;
    private float pressure;

    public void measurementsChanged(){
        setChanged();
        notifyObservers();//没有这一步表示观察者拉去信息,而不是推送
    }

    public void setMeasurements(float temperature,float humidity,float pressure){
        this.temperature=temperature;
        this.humidity=humidity;
        this.pressure=pressure;
        this.measurementsChanged();
    }

    //观察者可以通过以下方式拉去信息
    public float getPressure() {
        return this.pressure;
    }

    public float getHumidity() {
        return this.humidity;
    }

    public float getTemperature() {
        return this.temperature;
    }
}

观察者类

package com.jackeys.ObserverMode.JavaInner;

import java.util.Observable;
import java.util.Observer;

/**
 * @Description: 观察者类
 * @ClassName: CurrentConditionsDisplay
 * @Package com.jackeys.ObserverMode.JavaInner
 * @Author: Jackeys 1623427047@qq.com
 * @Copyright 版权归Jackeys企业(或个人)所有
 * @CreateTime: 2021/10/6 13:08
 * @Version: 1.0
 */
public class CurrentConditionsDisplay implements Observer,DisplayElement {
    private float temperature;
    private float humidity;
    private float pressure;
    private Observable observable;

    public CurrentConditionsDisplay(Observable observable){
        this.observable=observable;
        observable.addObserver(this);
    }
    @Override
    public void display() {
        System.out.println("现在的天气:温度 "+this.temperature+",湿度 "+this.humidity+",气压 "+this.pressure);
    }

    @Override
    public void update(Observable o, Object arg) {
        if(o instanceof WeatherData){
            WeatherData weatherData=(WeatherData) o;
            this.temperature=weatherData.getTemperature();
            this.humidity=weatherData.getHumidity();
            this.pressure=weatherData.getPressure();
            display();
        }
    }
}

测试

package com.jackeys.ObserverMode.JavaInner;

/**
 * @Description: 测试Java内置的观察者模式
 * @ClassName: Test
 * @Package com.jackeys.ObserverMode.JavaInner
 * @Author: Jackeys 1623427047@qq.com
 * @Copyright 版权归Jackeys企业(或个人)所有
 * @CreateTime: 2021/10/6 13:14
 * @Version: 1.0
 */
public class Test {
    public static void main(String[] args) {
        WeatherData weatherData=new WeatherData();
        CurrentConditionsDisplay currentConditionsDisplay=new CurrentConditionsDisplay(weatherData);
        CurrentConditionsDisplay currentConditionsDisplay1=new CurrentConditionsDisplay(weatherData);
        weatherData.setMeasurements(1.2f,1.3f,1.4f);
    }
}

输出
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值