行为模式-观察者模式

定义:

Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.(定义对象间一种一对多的依赖关系,使得每 当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。)

观察者模式通用类图

观察者设计模式的核心思想在于建立对象之间的依赖关系,并实现事件驱动的通知机制。被观察者维护一个观察者列表,当自身状态改变时,遍历该列表,主动调用每个观察者的更新方法,从而实现状态变化的自动传播。同时,观察者可以自由地注册到被观察者或从被观察者中注销,两者之间无需了解对方的具体实现细节,降低了对象之间的耦合度 。

角色:

观察者模式包含以下几个核心角色:

​1、抽象主题(Subject)

抽象主题是被观察对象的抽象类或接口,它定义了添加观察者、删除观察者以及通知观察者的抽象方法。同时,它还维护一个观察者对象的列表,用于存储所有注册的观察者。抽象主题是连接被观察者和观察者的桥梁,为具体被观察者提供统一的操作接口。

2、具体主题(ConcreteSubject)

具体主题是抽象主题的具体实现类,它负责实现抽象主题中定义的方法。当具体主题的状态发生改变时,它会调用抽象主题中通知观察者的方法,将状态变化告知所有注册的观察者。具体主题是实际被观察的对象,其状态变化会触发观察者的更新。

3、抽象观察者(Observer)

抽象观察者是观察者的抽象类或接口,它定义了一个更新方法,用于接收被观察者的通知,并在接收到通知后执行相应的操作。抽象观察者为具体观察者提供了统一的接口,使得具体观察者可以以一致的方式与被观察者进行交互。

4、具体观察者(ConcreteObserver)

具体观察者是抽象观察者的具体实现类,它实现了抽象观察者中定义的更新方法。在更新方法中,具体观察者根据接收到的被观察者的状态变化信息,执行具体的更新操作,如更新自身的显示、执行特定的业务逻辑等。具体观察者是实际接收通知并进行响应的对象。

代码示例:

以天气监测系统为例,气象站作为被观察者,用户作为观察者。当气象站监测到天气数据(温度、湿度、风速等)发生变化时,及时通知订阅天气信息的用户。

// 抽象观察者

java 复制代码
public interface Observer {

    void update(float temperature, float humidity, float windSpeed);

}

// 具体观察者,用户

java 复制代码
public class User implements Observer {

    private String name;



    public User(String name) {

        this.name = name;

    }



    @Override

    public void update(float temperature, float humidity, float windSpeed) {

        System.out.println(name + " 收到天气更新:温度 " + temperature + "℃,湿度 " + humidity + "%,风速 " + windSpeed + "m/s");

    }

}

// 抽象主题

java 复制代码
public interface Subject {

    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObservers();

}

// 具体主题,气象站

java 复制代码
public class WeatherStation implements Subject {

    private float temperature;

    private float humidity;

    private float windSpeed;

    private java.util.ArrayList<Observer> observers;



    public WeatherStation() {

        observers = new java.util.ArrayList<>();

    }



    @Override

    public void registerObserver(Observer observer) {

        observers.add(observer);

    }



    @Override

    public void removeObserver(Observer observer) {

        int i = observers.indexOf(observer);

        if (i >= 0) {

            observers.remove(i);

        }

    }



    @Override

    public void notifyObservers() {

        for (Observer observer : observers) {

            observer.update(temperature, humidity, windSpeed);

        }

    }



    public void setWeatherData(float temperature, float humidity, float windSpeed) {

        this.temperature = temperature;

        this.humidity = humidity;

        this.windSpeed = windSpeed;

        notifyObservers();

    }

}

// 客户端代码

java 复制代码
public class ObserverPatternClient {

    public static void main(String[] args) {

        WeatherStation weatherStation = new WeatherStation();



        User user1 = new User("Alice");

        User user2 = new User("Bob");



        weatherStation.registerObserver(user1);

        weatherStation.registerObserver(user2);



        weatherStation.setWeatherData(25, 60, 3);

        weatherStation.removeObserver(user1);

        weatherStation.setWeatherData(28, 55, 4);

    }

}

优点 :

**1、实现松耦合:**被观察者和观察者之间通过抽象接口进行交互,彼此无需了解对方的具体实现细节,降低了对象之间的耦合度。当被观察者或观察者的实现发生变化时,不会影响到对方,提高了系统的可维护性和扩展性。

**2、易于扩展:**可以方便地增加新的观察者或被观察者,而无需修改现有代码。新的观察者只需实现抽象观察者接口,然后注册到被观察者中即可接收通知;新的被观察者只需实现抽象主题接口,就能与现有的观察者进行交互。

**3、支持事件驱动编程:**观察者模式符合事件驱动的编程思想,能够实现对象状态变化的自动传播,使得系统能够及时响应各种事件,提高了系统的实时性和交互性。

缺点:

**1、内存泄漏风险:**如果观察者注册后没有正确注销,可能会导致观察者对象无法被垃圾回收,从而造成内存泄漏。特别是在长时间运行的系统中,需要特别注意观察者的生命周期管理。

**2、通知顺序不确定:**在被观察者通知观察者时,由于观察者列表的遍历顺序不确定,可能导致观察者接收到通知的顺序与预期不符。在某些对通知顺序有严格要求的场景中,需要额外处理来确保通知顺序的正确性。

**3、性能问题:**当观察者数量较多时,被观察者通知所有观察者的操作可能会带来一定的性能开销。尤其是在状态变化频繁的情况下,可能会影响系统的整体性能,需要考虑优化通知机制,如采用异步通知等方式。

使用场景:

(一)事件驱动的系统

当系统需要基于事件进行响应时,观察者模式非常适用。例如,图形用户界面(GUI)中的按钮点击事件、鼠标移动事件等,当用户触发这些事件(被观察者状态改变)时,相应的事件处理程序(观察者)会被调用,执行特定的操作 。

(二)消息订阅与发布系统

在消息订阅与发布系统中,消息发布者作为被观察者,消息订阅者作为观察者。订阅者可以根据自己的需求订阅感兴趣的消息主题,当发布者发布新消息时,自动通知所有订阅该主题的订阅者。这种模式在实时通信、新闻推送、邮件通知等场景中广泛应用。

(三)状态监控与预警系统

对于需要实时监控对象状态并在状态发生变化时进行预警的系统,观察者模式是一个很好的选择。例如,服务器监控系统中,当服务器的 CPU 使用率、内存占用率等指标超出阈值(被观察者状态改变)时,及时通知系统管理员(观察者),以便采取相应的措施。

观察者设计模式通过建立对象之间的一对多依赖关系,实现了状态变化的自动传播和对象间的动态联动。它在事件驱动系统、消息订阅与发布系统、状态监控与预警系统等众多领域有着广泛的应用。该模式具有松耦合、易于扩展等显著优点,但也存在内存泄漏风险、通知顺序不确定和性能问题等缺点。在实际开发中,我们应根据具体需求合理运用观察者设计模式,充分发挥其优势,同时注意规避其潜在的问题,从而编写出更加灵活、高效、可维护的代码。希望本文能帮助你深入理解观察者设计模式,并在今后的项目中熟练运用它解决实际问题。

相关推荐
Maybyy5 分钟前
力扣454.四数相加Ⅱ
java·算法·leetcode
Java中文社群8 分钟前
面试官:谈谈你AI项目的具体实现?
java·后端·面试
找了一圈尾巴38 分钟前
设计模式(结构型)-适配器模式
设计模式·适配器模式
哪里不会点哪里.40 分钟前
适配器模式:兼容不兼容接口
java·开发语言
vvilkim43 分钟前
单例模式详解:确保一个类只有一个实例
单例模式·设计模式
何中应1 小时前
Maven项目没有Maven工具,IDEA没有识别到该项目是Maven项目怎么办?
java·后端·maven·intellij-idea
neoooo1 小时前
Redis锁得住,世界就是你的:一探Redis分布式锁的原理、姿势与深度思考
java·redis·后端
CodeWithMe1 小时前
【读书笔记】《C++ Software Design》第六章深入剖析 Adapter、Observer 和 CRTP 模式
c++·设计模式
恸流失1 小时前
java基础-1 : 运算符
java·开发语言·数据结构
柳如烟@1 小时前
零基础入门Java虚拟机与单例模式:新手友好教程
java·开发语言·单例模式