深究设计模式之-观察者模式

观察者模式(Observer Pattern)是一种行为型设计模式,其主要目的是定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,所有依赖于它的观察者都得到通知并被自动更新。观察者模式使得主题对象和观察者对象之间保持松耦合,以便可以灵活地扩展和重用。

在观察者模式中发生改变的对象称为观察目标 ,而被通知的对象称为观察者,一个观察目标可以应对多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展.

比如我们生活中的等待红绿灯的汽车,红绿灯就是一个观察目标,而所有等待的汽车就是观察者。

主要角色:

  1. 主题(Subject): 也就是抽象的被观察者,负责维护一系列观察者对象,并通知它们状态的变化。

  2. 具体主题(Concrete Subject): 也就是具体的被观察者对象,实现了主题接口,负责状态的存储和变化,当状态发生变化时通知观察者。

  3. 观察者(Observer): 定义了一个更新接口,用于接收主题对象的通知。

  4. 具体观察者(Concrete Observer): 实现了观察者接口,当接收到主题对象的通知时进行相应的更新操作。

示例:

一个气象站的例子,气象站可以实时测量温度、湿度和气压,并通知观察者(如手机、电视等设备)。

java 复制代码
package com.luke.designpatterns.observerPattern;

import java.util.ArrayList;
import java.util.List;

// 抽象的被观察者
interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// 具体的被观察者 - 气象站
class WeatherStation implements Subject {
    private List<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

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

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

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

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }
}

// 抽象的观察者
interface Observer {
    void update(float temperature, float humidity, float pressure);
}

// 具体观察者 - 手机
class PhoneDisplay implements Observer {
    @Override
    public void update(float temperature, float humidity, float pressure) {
        System.out.println("Phone Display: Temperature - " + temperature + "°C, Humidity - " + humidity + "%");
    }
}

// 具体观察者 - 电视
class TVDisplay implements Observer {
    @Override
    public void update(float temperature, float humidity, float pressure) {
        System.out.println("TV Display: Pressure - " + pressure + "hPa");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建被观察者
        WeatherStation weatherStation = new WeatherStation();

        // 添加观察者
        Observer phoneDisplay = new PhoneDisplay();
        Observer tvDisplay = new TVDisplay();
        
        weatherStation.addObserver(phoneDisplay);
        weatherStation.addObserver(tvDisplay);

        // 模拟气象站测量并通知观察者
        weatherStation.setMeasurements(25.5f, 60.0f, 1012.5f);
    }
}

在这个例子中,WeatherStation 是具体的被观察者,负责测量气象信息并通知观察者。Observer 是观察者接口,定义了更新方法。PhoneDisplayTVDisplay 是具体观察者,实现了更新方法,并在接收到通知时进行相应的操作。

客户端代码创建了一个气象站作为主题,添加了手机和电视作为观察者。当气象信息发生变化时,主题通知观察者进行更新。观察者模式使得主题和观察者之间的关系变得灵活,可以方便地增加、删除观察者,同时确保主题对象不需要知道观察者的具体细节。

适用场景

观察者模式适用于以下场景:

  1. 对象间存在一对多的依赖关系: 当一个对象的变化需要通知多个其他对象时,观察者模式非常有用,因为它建立了一种松散耦合的关系。

比如图形界面中的事件处理。考虑一个按钮对象作为被观察者,而多个UI组件(比如文本框、复选框等)作为观察者。当按钮被点击时,所有注册的UI组件都能够接收到通知并执行相应的操作。

  1. 抽象模型有两个方面,其中一个依赖于另一方面: 当一个对象的状态变化需要影响到另一个对象,但又希望保持独立性时,可以考虑使用观察者模式。

比如股票市场。股票价格作为被观察者,而图表和报价服务作为观察者。当股票价格变化时,图表和报价服务能够接收到通知并更新显示的数据。

  1. 系统需要分布式事件处理: 观察者模式在实现分布式事件处理系统时很有用,因为它允许对象之间通过事件通知进行通信,而无需直接了解彼此的存在。

比如在线协作编辑器。文档的变化作为被观察者,而不同用户的编辑器作为观察者。通过观察者模式,文档的变化可以实时地通知到所有其他用户的编辑器,实现协同编辑功能。

  1. 动态更新情况: 当一个对象的改变需要动态地通知其他对象,并且不希望知道具体通知哪些对象时,观察者模式提供了一种灵活的解决方案。

比如一个天气应用程序。天气数据作为被观察者,而不同的天气组件(比如温度显示、风速显示等)作为观察者。当天气数据发生变化时,所有注册的天气组件都能够动态更新显示最新的天气信息。

总体来说,观察者模式适用于需要解耦对象之间依赖关系、实现松散耦合、并提供灵活性和可扩展性的情况。

相关推荐
机器视觉知识推荐、就业指导3 分钟前
C++设计模式:解释器模式(简单的数学表达式解析器)
c++·设计模式·解释器模式
苹果醋331 分钟前
Vue3响应式数据: 深入分析Ref与Reactive
java·运维·spring boot·mysql·nginx
缘友一世1 小时前
JAVA代理模式和适配器模式
java·代理模式·适配器模式
轻浮j1 小时前
Sentinel底层原理以及使用算法
java·算法·sentinel
it噩梦1 小时前
springboot 工程使用proguard混淆
java·spring boot·后端
潜意识起点1 小时前
Java数组:静态初始化与动态初始化详解
java·开发语言·python
竹影卿心1 小时前
Java连接HANA数据库
java·数据库·windows
Abelard_1 小时前
LeetCode--347.前k个高频元素(使用优先队列解决)
java·算法·leetcode
海海不掉头发1 小时前
软件工程-【软件项目管理】--期末复习题汇总
java·学习·产品运营·软件工程·团队开发·需求分析·期末复习
缘友一世1 小时前
java实现网络IO高并发编程java AIO
java·网络·python