掌握设计模式--观察者模式

观察者模式(Observer Pattern)

观察者模式(Observer Pattern)是一种行为设计模式,它定义了对象间的一对多依赖关系,使得当一个对象状态发生改变时,所有依赖于它的对象都会自动收到通知并更新。

主要组成部分

主题(Subject) :主题是被观察的对象,它维护一个观察者列表。当它的状态发生改变时,会通知所有的观察者。主题提供方法来注册、注销观察者。

观察者(Observer):观察者是依赖于主题的对象,它会在主题状态发生变化时收到通知,进而更新自身的状态。观察者有一个更新方法,当主题状态变化时,主题会调用此方法来通知观察者。

工作流程

  1. 注册观察者:观察者通过主题提供的注册方法将自己注册到主题上。
  2. 状态变化:主题的状态发生变化时,它会遍历其所有注册的观察者。
  3. 通知观察者:主题调用每个观察者的更新方法,通知它们进行状态更新。
  4. 更新观察者:观察者根据通知更新自己的状态,通常会重新渲染界面或进行其他的状态更新。

案例实现

假设有一个温度监控系统:

  • 主题:温度传感器,当温度发生变化时,它会通知所有依赖于它的观察者。
  • 观察者:可以是不同的显示设备或报警系统,温度变化时,它们会根据新温度执行相应操作。

案例类图

观察者接口

用于观察温度变化的接口,订阅的主题发生变化时,通过观察者接口的update方法来通知订阅了的所有观察者。

java 复制代码
interface Observer {
    void update(int temperature);
}

观察者实现类

java 复制代码
// 观察者实现类1
class DisplayDevice implements Observer {
    @Override
    public void update(int temperature) {
        System.out.println("显示装置:温度更新到" + temperature);
    }
}

// 观察者实现类2
class AlarmSystem implements Observer {
    @Override
    public void update(int temperature) {
        if (temperature > 42) {
            System.out.println("警报:温度超过阈值!");
        }
    }
}

主题类(被观察者)

java 复制代码
class TemperatureSensor {
    // 观察者列表
    private List<Observer> observers = new ArrayList<>();
    private int temperature;

    // 注册观察者
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    // 移除观察者
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    // 设置温度并通知观察者
    public void setTemperature(int temperature) {
        this.temperature = temperature;
        notifyObservers();
    }

    // 通知所有观察者
    private void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature);
        }
    }
}

测试客户端

java 复制代码
public class ObserverPatternDemo {
    public static void main(String[] args) {
        // 创建主题和观察者
        TemperatureSensor sensor = new TemperatureSensor();
        Observer display = new DisplayDevice();
        Observer alarm = new AlarmSystem();

        // 注册观察者:如果没注册,那就不会通知
        sensor.addObserver(display);
        sensor.addObserver(alarm);

        // 改变主题的状态
        sensor.setTemperature(45);
        sensor.setTemperature(28);
    }
}

测试输出结果

显示装置:温度更新到45

警报:温度超过阈值!

显示装置:温度更新到28

优缺点和使用场景

优点

  1. 松耦合:观察者与主题之间是松耦合的,主题不需要知道具体的观察者,观察者也不需要了解主题的内部实现。
  2. 动态添加或删除观察者:可以在运行时动态地添加或删除观察者。

缺点

  1. 多次更新:如果有大量观察者,状态变化可能导致多次调用更新方法,性能可能受到影响。
  2. 循环依赖:观察者之间如果互相通知更新,可能引起循环依赖或无限循环。

观察者模式是处理事件驱动系统或需要多个对象同步更新状态的常用模式,尤其在分布式系统、GUI框架中应用广泛。

适用场景

  • 事件驱动的系统:例如GUI框架(按钮点击、界面更新等)、消息通知系统等。
  • 发布-订阅系统:如消息队列系统、新闻订阅、社交媒体更新等。
  • 数据同步:多个模块需要同步更新某些共享数据时,如温度监控、股票价格变化等。

观察者模式的应用

Spring的事件机制ApplicationEvent是事件对象,ApplicationListener是事件监听器,当ApplicationEvent发布时,所有注册了该事件类型的ApplicationListener会被通知并处理该事件。ApplicationEventPublisher接口(通常是ApplicationContext的实现类)作为被观察者,ApplicationListener作为观察者。事件的发布和监听实现了松耦合的通知机制。

Java Web中的监听器,它通过监听和响应Web应用的生命周期事件、HTTP会话事件、请求事件以及属性变化事件。常见的监听器接口包括ServletContextListenerHttpSessionListenerServletRequestListener等,实现相应的监听接口,即可完成相应事件的监听。监听器机制的使用可以帮助开发者在特定事件发生时执行一些处理逻辑,保证代码的解耦和灵活性。

总结

观察者模式是一种行为设计模式,其核心在于通过定义一对多的依赖关系,使得当被观察者的状态发生变化时,所有依赖的观察者自动收到通知并更新,从而实现对象之间的松耦合和动态响应,同时便于观察者的扩展。

需要查看往期设计模式文章的,可以在个人主页中或者文章开头的集合中查看,可关注我,持续更新中。。。


超实用的SpringAOP实战之日志记录

2023年下半年软考考试重磅消息

通过软考后却领取不到实体证书?

计算机算法设计与分析(第5版)

Java全栈学习路线、学习资源和面试题一条龙

软考证书=职称证书?

软考中级--软件设计师毫无保留的备考分享