设计模式从入门到精通之(五)观察者模式

观察者模式:实现高效事件通知的秘诀

在日常生活中,我们经常需要同步通知多方的信息变更。比如天气预报系统、股票价格波动提醒、社交媒体的点赞通知等。这些场景中,通知机制需要高效、灵活,而不会因为通知方的变化影响系统整体。

观察者模式正是为这种场景而设计的解决方案。


1. 什么是观察者模式?

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

用一句话概括:观察者模式实现了事件驱动机制,解耦了事件发生者和响应者之间的关系。


2. 现实生活中的观察者模式

想象一下,你订阅了一个股票提醒服务。每当股票价格达到你的预期,系统就会向你发送短信通知。而且不仅是你,很多其他订阅用户也会接到各自定制化的提醒。

在这个场景中:

  1. 股票价格变动是主题(Subject)。
  2. 每个订阅用户是观察者(Observer)。
  3. 当主题状态变化时,所有观察者都会收到通知。

3. 观察者模式的代码实现

以一个天气预报系统为例,展示观察者模式的实现。

3.1 定义主题接口

首先,定义一个通用的主题接口,允许观察者订阅或取消订阅。

java 复制代码
interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

3.2 定义观察者接口

然后,定义观察者接口,让所有具体观察者实现自己的更新逻辑。

java 复制代码
interface Observer {
    void update(String weather);
}
3.3 实现具体的主题类

创建一个天气数据的主题类,用来管理观察者并发送通知。

java 复制代码
import java.util.ArrayList;
import java.util.List;

class WeatherData implements Subject {
    private List<Observer> observers;
    private String weather;

    public WeatherData() {
        observers = new ArrayList<>();
    }

    @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(weather);
        }
    }

    public void setWeather(String weather) {
        this.weather = weather;
        notifyObservers();
    }
}

3.4 实现具体的观察者

创建具体的观察者,比如手机用户和电视用户。

java 复制代码
class PhoneUser implements Observer {
    private String name;

    public PhoneUser(String name) {
        this.name = name;
    }

    @Override
    public void update(String weather) {
        System.out.println(name + " received weather update: " + weather);
    }
}

class TVUser implements Observer {
    @Override
    public void update(String weather) {
        System.out.println("TV displays weather update: " + weather);
    }
}

3.5 客户端代码

在客户端中,测试天气预报系统。

java 复制代码
public class Main {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();

        Observer phoneUser1 = new PhoneUser("Alice");
        Observer phoneUser2 = new PhoneUser("Bob");
        Observer tvUser = new TVUser();

        weatherData.addObserver(phoneUser1);
        weatherData.addObserver(phoneUser2);
        weatherData.addObserver(tvUser);

        weatherData.setWeather("Sunny");
        weatherData.setWeather("Rainy");
    }
}

运行结果:

复制代码
Alice received weather update: Sunny
Bob received weather update: Sunny
TV displays weather update: Sunny
Alice received weather update: Rainy
Bob received weather update: Rainy
TV displays weather update: Rainy

4. 观察者模式的优缺点

优点:

  1. 解耦发布者和订阅者:主题只需管理观察者列表,不关心观察者的具体实现。
  2. 灵活性高:可以动态添加或移除观察者。
  3. 扩展性强:新增观察者不需要修改主题代码。

缺点:

  1. 通知链复杂:观察者数量较多时,通知链可能导致性能问题。
  2. 可能引发循环依赖:需要避免观察者反向修改主题导致死循环。

5. 观察者模式的应用场景

  1. 事件驱动系统:比如 GUI 中的按钮点击事件。
  2. 消息订阅机制:如消息队列、Kafka 等系统。
  3. 数据绑定框架:如 Angular 的双向绑定。
  4. 系统监控:服务器状态变化时通知管理员。

6. 总结

观察者模式是一种高效的事件通知机制,特别适合需要动态响应状态变化的场景。在实际开发中,我们可以结合异步通知、线程安全等技术,进一步优化观察者模式的性能。

下一篇专栏,我们将继续探索行为型模式中的另一种经典模式:策略模式,看它如何帮助我们灵活地实现算法的动态切换。


思考问题:

在复杂场景下,如何防止观察者模式中的通知链导致性能问题?欢迎留言讨论!

相关推荐
庄小焱3 小时前
设计模式——中介者设计模式(行为型)
设计模式
庄小焱5 小时前
设计模式——备忘录设计模式(行为型)
设计模式
庄小焱5 小时前
设计模式——代理设计模式(结构型)
设计模式
哆啦A梦的口袋呀6 小时前
基于Python学习《Head First设计模式》第三章 装饰者模式
python·学习·设计模式
哆啦A梦的口袋呀6 小时前
基于Python学习《Head First设计模式》第五章 单件模式
python·学习·设计模式
季鸢7 小时前
Java设计模式之备忘录模式详解
java·设计模式·备忘录模式
摘星编程10 小时前
工厂方法模式深度解析:从原理到应用实战
java·设计模式·软件工程·工厂方法模式
何中应11 小时前
【设计模式-4.7】行为型——备忘录模式
java·设计模式·备忘录模式
suixinger_lmh1 天前
功能结构整理
unity·设计模式·c#·源代码管理
冰茶_1 天前
建造者模式:优雅构建复杂对象
设计模式·微软·c#·.netcore·建造者模式·软件开发