Java行为型设计模式-观察者模式

1. 观察者模式简介

观察者模式(Observer Pattern)是行为型设计模式之一,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

46018acdc4c8443fbbb03e1541a51693.png

在Java中,观察者模式通常通过java.util.Observable类和java.util.Observer接口实现,但是由于Observable类的方法都是同步的,可能会影响程序的灵活性和并发性,因此在Java 1.0版本之后,推荐使用Java.util.concurrent包下的BlockingQueue作为替代方案。

2. 观察者模式角色

89005d95a4e84fdd89fb5a5b463ce5dd.png

在Java中,观察者模式通常涉及到以下几个角色:

 2.1 Subject(目标)

 目标是被观察的对象。它提供了添加、删除观察者的接口,并在自身内部状态改变时通知观察者。

2.2 Observer(观察者)

观察者接口定义了一个更新方法,当目标的状态发生改变时,观察者会接收到通知并调用这个方法。

2.3 ConcreteSubject(具体目标)

实现了Subject的具体类,包含有关状态的通知方法。

2.4 ConcreteObserver(具体观察者)

实现了Observer接口的具体类,包含一个更新方法,当收到通知时会执行这个方法。 

3. 观察者模式应用场景

7affc015780743f99ec08d57956fcacb.png

观察者模式的应用场景非常广泛,主要包括‌:

‌3.1 发布-订阅系统‌

观察者模式是发布-订阅模式的核心。当发布者发布新消息或事件时,所有订阅者都会收到通知并执行相应的操作‌。

‌3.2 事件处理机制‌

观察者模式用于处理事件驱动的编程。事件触发时,事件源对象会通知事件处理程序(观察者),以执行相应的操作‌。

‌3.3 实时数据更新‌

在需要实时更新数据的应用中,观察者模式可以用于将数据源与数据消费者连接起来。当数据源的数据发生变化时,观察者可以自动获取最新的数据进行处理‌。

3.4 ‌库和框架‌

许多编程库和框架使用观察者模式来支持插件和扩展。开发人员可以编写自定义观察者以响应库或框架中的事件或回调‌。

‌3.5 消息队列系统‌

观察者模式可用于消息队列系统,其中生产者将消息发送到队列,而消费者作为观察者订阅队列以接收和处理消息‌。

3.6 ‌股票市场监测‌

股票市场应用程序可以使用观察者模式来监测股票价格变化,并将这些变化通知给投资者‌。

3.7 ‌游戏开发‌

在游戏中,观察者模式可用于处理各种事件,如玩家输入、碰撞检测、角色状态变化等‌。

3.8 ‌网络通信‌

在网络应用中,观察者模式可用于实现即时通信系统,其中用户之间的消息传递可以通过观察者模式来实现‌。

3.9 MVC架构设计

其中模型(Model)可以对应观察者模式中的观察目标,而视图(View)对应于观察者,控制器(Controller)则是中介者模式的应用场景之一‌。

4. 观察者模式优缺点

观察者模式在设计和实现对象间的动态一对多关系时非常有用,有诸多优点,尤其是在需要避免紧耦合的场景中。然而,使用时需要注意上述优缺点,以确保系统的稳定性和效率‌。

4.1 观察者模式的优点

  1. 解耦‌:观察者模式允许被观察者(主题)和观察者之间建立一种抽象的耦合关系,而不是紧密的依赖关系。这意味着被观察者不需要知道具体的观察者是谁,只需要知道它们都符合一个共同的接口。这种解耦使得被观察者和观察者可以独立变化,互不影响‌。
  2. 灵活性‌:基于接口的设计使得观察者模式具有很高的灵活性。可以灵活地添加新的观察者或改变观察者的行为,而不需要修改被观察者的代码。这种灵活性为程序提供了更大的设计空间‌。
  3. 维护一致性‌:通过建立松散的依赖关系,观察者模式有助于维护系统的一致性。当被观察者的状态发生变化时,所有依赖于此状态的观察者都会得到通知并进行更新,从而保持系统的一致性‌。

4.2 观察者模式缺点

  1. 过多的通知‌:当被观察者对象有很多直接和间接的观察者时,每次状态变化都需要通知所有观察者,这可能会花费很多时间,尤其是在有大量观察者的情况下,可能会影响程序的执行效率‌。
  2. 循环依赖问题‌:如果观察者和被观察者之间存在循环依赖,可能会导致系统崩溃。在使用观察者模式时,需要特别注意这一点,以避免出现循环调用的情况‌。
  3. 开发调试复杂‌:应用观察者模式时,需要考虑开发小路问题,包括被观察者和多个观察者的管理和调试,这可能会增加开发的复杂性‌。
  4. 没有提供变化细节‌:观察者模式只能让观察者知道被观察对象的变化,但不能提供关于变化的具体细节,这意味着观察者只能知道发生了变化,但不知道是如何变化的‌。

5. 观察者模式代码示例

      

25229fb3d26a435cbe3bf6f9ab2eff5f.png

  

以下是一个简单的观察者模式的实现:

// 观察者接口
interface Observer {
    void update(float temp, float humidity, float pressure);
}
 
// 目标接口
interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObservers();
}
 
// 具体目标类
class WeatherData implements Subject {
    private ArrayList<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;
 
    public WeatherData() {
        observers = new ArrayList<>();
    }
 
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }
 
    @Override
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if (i >= 0) {
            observers.remove(i);
        }
    }
 
    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }
 
    // 当获取到新的测量数据时,通知观察者
    public void measurementsChanged() {
        notifyObservers();
    }
 
    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
}
 
// 具体观察者类
class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;
 
    @Override
    public void update(float temp, float humidity, float pressure) {
        this.temperature = temp;
        this.humidity = humidity;
        display();
    }
 
    public void display() {
        System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
    }
}
 
// 使用观察者模式的示例
public class WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
 
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
        weatherData.registerObserver(currentDisplay);
 
        // 当气象测量更新时,观察者会接收到通知
        weatherData.setMeasurements(80, 65, 30.4f);
    }
}

在这个例子中,WeatherData类实现了Subject接口,负责存储气象数据,并在数据更新时通知观察者。CurrentConditionsDisplay类实现了Observer接口,用于显示当前的气象状况。当WeatherData的气象数据更新时,它会调用measurementsChanged()方法,通知所有注册的观察者。观察者接收到通知后,会调用它们的update方法来更新自身状态。

6. 总结

综上,观察者模式是软件设计模式中的一种,在此种模式中,一个目标对象管理所有依赖于其的观察者对象,并且当自身的状态改变时,会通知观察者对象,使它们能够自动更新

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙殿殿主

你的打赏是我精心创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值