设计模式详解——观察者模式

设计模式详解------观察者模式

一、模式概述

1. 模式定义

观察者模式(Observer Pattern) 也叫发布-订阅模式(Publish-Subscribe Pattern) ,是一种行为型设计模式。

它定义对象间一种一对多的依赖关系:

  • 一:一个主题(被观察者)
  • 多:多个观察者

当主题对象的状态发生改变时,所有依赖它的观察者都会收到通知并自动更新。

2. 核心思想

  • 一对多依赖,松耦合
  • 被观察者只管发布通知,不关心谁在监听
  • 观察者只管订阅并响应,不关心谁发出事件
  • 状态变化自动传播,无需主动轮询

3. 主要角色

  1. 抽象主题(Subject)
    提供注册、移除、通知观察者的接口
  2. 具体主题(ConcreteSubject)
    维护状态,状态变化时通知所有观察者
  3. 抽象观察者(Observer)
    定义收到通知后的更新接口
  4. 具体观察者(ConcreteObserver)
    实现更新逻辑,处理自身业务
  5. 客户端(Client)
    创建主题与观察者,建立订阅关系

二、适用场景

  1. 一个对象状态改变,需要自动通知其他多个对象
  2. 系统需要解耦发布方与订阅方
  3. 事件驱动、消息广播、状态同步场景
  4. 框架中的事件机制、监听机制

典型业务场景:

  • 订单状态变更通知(用户、物流、库存)
  • 商品降价提醒
  • 聊天室消息推送
  • 配置变更实时生效
  • 前端事件监听、Spring 事件模型

三、实战代码实现(模拟订单状态通知)

场景说明

订单状态改变时,需要同时通知:

  1. 用户(短信/APP推送)
  2. 物流系统(准备发货)
  3. 库存系统(扣减完成)

使用观察者模式实现一对多通知。

1. 抽象观察者

java 复制代码
/**
 * 抽象观察者
 */
public interface Observer {
    // 收到通知后执行的方法
    void update(String orderStatus);
}

2. 具体观察者 A:用户通知

java 复制代码
public class UserObserver implements Observer {
    @Override
    public void update(String orderStatus) {
        System.out.println("【用户通知】订单状态更新:" + orderStatus + ",已推送APP消息");
    }
}

3. 具体观察者 B:物流系统

java 复制代码
public class LogisticsObserver implements Observer {
    @Override
    public void update(String orderStatus) {
        if ("已支付".equals(orderStatus)) {
            System.out.println("【物流系统】准备打包发货");
        }
    }
}

4. 具体观察者 C:库存系统

java 复制代码
public class StockObserver implements Observer {
    @Override
    public void update(String orderStatus) {
        if ("已支付".equals(orderStatus)) {
            System.out.println("【库存系统】确认扣减库存完成");
        }
    }
}

5. 抽象主题

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

/**
 * 抽象主题(被观察者)
 */
public interface Subject {
    // 注册观察者
    void attach(Observer observer);
    // 移除观察者
    void detach(Observer observer);
    // 通知所有观察者
    void notifyObservers();
}

6. 具体主题:订单主题

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

/**
 * 订单主题:状态变化时通知所有人
 */
public class OrderSubject implements Subject {

    private List<Observer> observerList = new ArrayList<>();
    private String orderStatus;

    // 状态变更
    public void setOrderStatus(String orderStatus) {
        this.orderStatus = orderStatus;
        // 状态变了 → 通知观察者
        notifyObservers();
    }

    @Override
    public void attach(Observer observer) {
        observerList.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observerList) {
            observer.update(orderStatus);
        }
    }
}

7. 客户端测试

java 复制代码
public class Client {
    public static void main(String[] args) {
        // 1. 创建主题(订单)
        OrderSubject orderSubject = new OrderSubject();

        // 2. 创建观察者
        UserObserver userObserver = new UserObserver();
        LogisticsObserver logisticsObserver = new LogisticsObserver();
        StockObserver stockObserver = new StockObserver();

        // 3. 注册订阅
        orderSubject.attach(userObserver);
        orderSubject.attach(logisticsObserver);
        orderSubject.attach(stockObserver);

        // 4. 改变订单状态 → 自动通知
        System.out.println("===== 订单状态变为:已支付 =====");
        orderSubject.setOrderStatus("已支付");
    }
}

8. 运行结果

复制代码
===== 订单状态变为:已支付 =====
【用户通知】订单状态更新:已支付,已推送APP消息
【物流系统】准备打包发货
【库存系统】确认扣减库存完成

四、Java 内置观察者(了解)

Java 提供原生支持:

  • 被观察者:java.util.Observable(类)
  • 观察者:java.util.Observer(接口)

缺点:

  • Observable 是类,不是接口,无法多继承
  • 线程不安全,功能简单
    实际开发一般自己实现或使用 Guava、Spring 事件。

五、观察者模式优缺点

优点

  1. 松耦合:发布者与订阅者互不依赖,可独立扩展
  2. 动态灵活:可随时增删观察者
  3. 符合开闭原则:新增观察者无需修改主题
  4. 广播机制:一次状态变更,多方同步

缺点

  1. 观察者过多时,通知效率下降
  2. 循环依赖可能导致死循环
  3. 观察者只知道主题变化,不知道如何变化
  4. 调试链路较长

六、经典框架应用(面试高频)

1. Spring Event 事件机制

  • ApplicationEvent(事件)
  • ApplicationListener(观察者)
  • ApplicationContext(发布者)

2. RabbitMQ / Kafka / RocketMQ

消息队列是异步化、分布式版的观察者模式。

3. GUI 事件监听

按钮点击事件 onClickListener 是典型观察者。

4. MyBatis 插件机制

底层使用观察者思想实现拦截与增强。

5. ZooKeeper Watch 机制

节点变化自动通知客户端。


七、观察者模式 VS 责任链模式(面试对比)

对比项 观察者模式 责任链模式
结构 一对多 一对一链式
通知方式 广播给所有人 依次传递,直到被处理
耦合 低 中等
目的 同步状态、广播通知 分级处理、权限过滤

八、总结

  1. 观察者模式 = 发布 + 订阅
  2. 核心:一对多、状态自动通知、松耦合
  3. 被观察者只负责通知,不关心观察者逻辑
  4. 适合事件驱动、状态同步、消息广播场景
  5. 是 Spring、消息队列、事件驱动架构的核心思想

一句话记忆:一个主题多监听,状态一变全通知;解耦发布与订阅,事件驱动最常用!


相关推荐
沫璃染墨11 小时前
《Linux工程实践篇(一):认识设计模式——从日志系统看策略模式》
linux·c++·安全·设计模式·策略模式
十六宿舍13 小时前
【软件设计模式-第一课:基础知识了解】
设计模式·架构·面向对象·软件架构
geovindu16 小时前
rust: Facade Pattern
开发语言·后端·设计模式·rust·外观模式
怕浪猫18 小时前
面试官让我手写一个 Tool Use,我用了 3 种方案
设计模式·面试·程序员
geovindu1 天前
rust: Abstract Factory pattern
开发语言·后端·设计模式·rust·抽象工厂模式
Carl_奕然2 天前
【智能体】Loop 的四种设计模式之:Event-Driven Loop(2026 最新版)
人工智能·驱动开发·python·设计模式
Carl_奕然2 天前
【智能体】Loop 的四种设计模式之:Hill Climbing Loop(2026 最新版)
人工智能·python·设计模式
晚安code3 天前
设计模式入门:吃透 SOLID 原则与迪米特法则,再学 5 个高频模式
后端·设计模式
染指11103 天前
135.Agent-多Agent框架-LangChain多智能体(SubAgents子代理)
数据库·人工智能·设计模式·langchain·agent·agents
路弥行至4 天前
【Head First 设计模式】第 2 章:观察者模式 —— 用现代 C++ 重新解读“交互对象的松耦合
c++·经验分享·笔记·观察者模式·设计模式·入门教程·headfirst