Java设计模式—观察者模式

本文介绍了观察者模式在Java中的应用,以气象站发布气象数据为例,展示了如何通过观察者模式实现气象数据的实时推送。传统方案中,第三方需主动获取数据,而观察者模式则允许动态注册和移除观察者,简化了系统扩展。JDK的Observable类作为观察者模式的实现,其源码与案例代码结构相似,易于理解。观察者模式的主要优点是通过集合管理观察者,方便注册、移除和通知操作,保持了数据维护类的独立性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

观察者模式

业务需求

  • 气象站需要测量温度、湿度、气压,发布到平台上
  • 需要开放型API,便于第三方可以接入获取气象数据
  • API可以提供气象参数的接口,气象站更新数据时可以实时通知第三方

传统方案

-创建天气类,通过get方法让第三方获取信息

  • 气象站通过change方法更新数据,第三方法下次获取数据时就会更新,这是第三方主动获取数据
  • 第三方也可以被动接收数据;需要推送时,引入第三方的对象,调用他们的update方法进行推送更新

传统方式代码

气象接收方

// 显示天气情况,可以理解为气象站自己的网站
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();
    }
    // 显示
    private void display() {
        System.out.println("温度: " + temperature + "******");
        System.out.println("气压: " + pressure + "******");
        System.out.println("湿度: " + humidity + "******");
    }
}

气象站提供信息

// 天气类,提供最新天气消息;引入CurrentConditions对象,用来推送天气消息
public class WeatherData {
    private float temperature;
    private float pressure;
    private float humidity;
    private CurrentConditions currentConditions;
    public WeatherData(CurrentConditions currentConditions) {
        this.currentConditions = currentConditions;
    }
    public float getTemperature() {
        return temperature;
    }
    public float getPressure() {
        return pressure;
    }
    public float getHumidity() {
        return humidity;
    }
    public void dataChange() {
        currentConditions.update(getTemperature(), getPressure(), getHumidity());
    }
    public void setData(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        dataChange();
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        // 接入方
        CurrentConditions currentConditions = new CurrentConditions();
        // 天气类
        WeatherData weatherData = new WeatherData(currentConditions);
        // 更新天气情况
        weatherData.setData(30, 0.9f, 13.5f);
        // 天气变化
        System.out.println("===========更新天气===========");
        weatherData.setData(31, 1.1f, 12.3f);
    }
}

传统解决方案问题

  • 如果增加第三方接收平台,需要增加第三方平台类,修改天气类中多个方法,比较麻烦;不利于维护,不利于动态加入;
  • 违反OCP模式;可以使用观察者模式解决

观察者模式解决

在这里插入图片描述
观察者接口

// 观察者接口
public interface Observer {
    public void update(float temperature, float pressure, float humidity);
}

观察者

public class CurrentConditions implements Observer{
    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();
    }
    // 显示
    private void display() {
        System.out.println("主站-温度: " + temperature + "******");
        System.out.println("主站-气压: " + pressure + "******");
        System.out.println("主站-湿度: " + humidity + "******");
    }
}
public class BaiduSite implements Observer{
    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();
    }
    // 显示
    private void display() {
        System.out.println("BaiduSite-温度: " + temperature + "******");
        System.out.println("BaiduSite-气压: " + pressure + "******");
        System.out.println("BaiduSite-湿度: " + humidity + "******");
    }
}

天气类接口

// 天气接口
public interface Subject {
    // 注册观察者
    public void registerObserver(Observer observer);
    // 移除观察者
    public void removeObserver(Observer observer);
    // 发布信息
    public void notifyObserver();
}

天气类,维护数据以及管理观察者

// 天气类,提供最新天气消息;引入观察者集合,用来推送天气消息
public class WeatherData implements Subject{
    private float temperature;
    private float pressure;
    private float humidity;
    // 观察者集合
    private ArrayList<Observer> observers;
    public WeatherData() {
        this.observers = new ArrayList<>();
    }
    public float getTemperature() {
        return temperature;
    }
    public float getPressure() {
        return pressure;
    }
    public float getHumidity() {
        return humidity;
    }
    public void dataChange() {
        notifyObserver();
    }
    public void setData(float temperature, float pressure, float humidity) {
        this.temperature = temperature;
        this.pressure = pressure;
        this.humidity = humidity;
        dataChange();
    }
    // 维护观察者
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }
    @Override
    public void removeObserver(Observer observer) {
        if (observers.contains(observer)) {
            observers.remove(observer);
        }
    }
    @Override
    public void notifyObserver() {
        for (Observer observer : observers) {
            observer.update(this.temperature, this.pressure, this.humidity);
            System.out.println("===============分割线==============");
        }
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        // 创建天气类
        WeatherData weatherData = new WeatherData();
        // 观察者
        CurrentConditions currentConditions = new CurrentConditions();
        BaiduSite baiduSite = new BaiduSite();
        // 注册到天气类
        weatherData.registerObserver(currentConditions);
        weatherData.registerObserver(baiduSite);
        // 不要的观察者可以移除
        // weatherData.removeObserver(baiduSite);
        // 发布天气,通知观察者
        weatherData.setData(18f, 0.85f, 12.8f);
    }
}

在这里插入图片描述

JDK源码分析—Observable

java.util.Observable

在这里插入图片描述
源码比较较好理解,基本与案例代码结构一致

观察者模式优势

  • 通过集合的方式来管理用户,可以对其注册、移除 、通知
  • 变动观察者不会影响到维护数据和管理的类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值