23种设计模式之观察者模式

以下是 观察者模式 (Observer Pattern) 的详细介绍,包含定义、优缺点、应用场景及代码实现:


一、观察者模式概述

  • 英文名称:Observer

  • 核心目标定义对象间的一对多依赖关系,当一个对象(被观察者)状态改变时,所有依赖它的对象(观察者)自动收到通知并更新

  • 设计思想:通过解耦被观察者和观察者,实现松耦合的动态事件通知机制。


二、优缺点

优点
  1. 解耦性强:被观察者和观察者相互独立,可单独修改。

  2. 动态订阅:支持运行时动态添加或移除观察者。

  3. 广播通信:一对多通知机制,简化事件传播。

缺点
  1. 性能开销:观察者数量多时,遍历通知可能耗时。

  2. 循环依赖:不当设计可能导致循环触发更新。

  3. 更新顺序不可控:观察者接收通知的顺序不确定。


三、应用场景

  1. 事件驱动系统:如 GUI 按钮点击事件、游戏角色状态变化。

  2. 数据监控:如股票价格波动通知、传感器数据更新。

  3. 消息中间件:如 Kafka、RabbitMQ 的发布-订阅模型。

  4. 配置中心热更新:配置变更后自动同步到多个服务。


四、代码实现与注释

以下通过 气象站数据发布系统 的案例演示观察者模式:


1. 观察者接口(订阅者)

/**
 * 观察者接口:定义数据更新方法
 */
public interface Observer {
    void update(float temperature, float humidity);
}

2. 被观察者接口(发布者)

/**
 * 被观察者接口:定义订阅、取消订阅和通知方法
 */
public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

3. 具体被观察者(气象站)

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

/**
 * 具体被观察者:气象站(维护观察者列表并通知数据变化)
 */
public class WeatherStation implements Subject {
    private final List<Observer> observers = new ArrayList<>();
    private float temperature;
    private float humidity;

    // 注册观察者
    @Override
    public void registerObserver(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);
        }
    }

    // 气象站数据更新时触发通知
    public void setMeasurements(float temperature, float humidity) {
        this.temperature = temperature;
        this.humidity = humidity;
        notifyObservers();
    }
}

4. 具体观察者(显示设备)

/**
 * 具体观察者:手机显示设备
 */
public class MobileDisplay implements Observer {
    @Override
    public void update(float temperature, float humidity) {
        System.out.println("[手机] 温度: " + temperature + "°C, 湿度: " + humidity + "%");
    }
}

/**
 * 具体观察者:电视显示设备
 */
public class TVDisplay implements Observer {
    @Override
    public void update(float temperature, float humidity) {
        System.out.println("[电视] 当前气象数据 => 温度: " + temperature + "°C, 湿度: " + humidity + "%");
    }
}

5. 客户端调用

public class Client {
    public static void main(String[] args) {
        // 创建被观察者(气象站)
        WeatherStation weatherStation = new WeatherStation();

        // 创建观察者(显示设备)
        Observer mobileDisplay = new MobileDisplay();
        Observer tvDisplay = new TVDisplay();

        // 注册观察者
        weatherStation.registerObserver(mobileDisplay);
        weatherStation.registerObserver(tvDisplay);

        // 更新气象数据,自动触发通知
        System.out.println("===== 第一次数据更新 =====");
        weatherStation.setMeasurements(25.5f, 65.0f);

        // 移除一个观察者后再次更新
        weatherStation.removeObserver(tvDisplay);
        System.out.println("\n===== 第二次数据更新 =====");
        weatherStation.setMeasurements(28.0f, 60.0f);
    }
}

6. 输出结果

===== 第一次数据更新 =====
[手机] 温度: 25.5°C, 湿度: 65.0%
[电视] 当前气象数据 => 温度: 25.5°C, 湿度: 65.0%

===== 第二次数据更新 =====
[手机] 温度: 28.0°C, 湿度: 60.0%

五、模式结构图

+----------------+          +----------------+
|   Subject      | <>-----+ |   Observer     |
+----------------+          +----------------+
| +register()    |          | +update()      |
| +remove()      |          +----------------+
| +notify()      |
+----------------+
       ^
       |
+----------------+
| ConcreteSubject|
+----------------+
| +getState()    |
| +setState()    |
+----------------+
       |
       |
+----------------+
| ConcreteObserver|
+----------------+
| +update()      |
+----------------+

六、与其他模式的关系

  1. 发布-订阅模式:观察者模式是发布-订阅的基础,后者通常引入中间代理层(如消息队列)。

  2. 中介者模式:中介者协调多个对象间通信,观察者模式侧重单向通知。

  3. 责任链模式:观察者广播通知,责任链按链传递请求。


七、最佳实践

  1. Java 内置支持java.util.Observable 和 java.util.Observer(但 Observable 类已过时,建议自定义实现)。

  2. 异步通知:使用线程池或消息队列异步处理观察者更新,避免阻塞。

  3. 防止竞态条件:确保在遍历观察者列表时线程安全(如使用 CopyOnWriteArrayList)。


八、总结

  • 核心价值:解耦事件发布者与订阅者,实现动态、灵活的事件通知机制。

  • 适用场景:需要实现事件驱动、数据同步或状态监听功能的系统。

  • 关键实现:被观察者接口 + 观察者接口 + 注册/通知机制。

观察者模式在 Java 生态中广泛应用,例如:

  • Swing/AWTActionListener 监听按钮点击事件。

  • Spring 事件机制ApplicationEvent 和 ApplicationListener

  • ReactiveX:RxJava 的 Observable 和 Observer 实现响应式编程。

掌握该模式能有效提升系统的可扩展性和模块化程度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值