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

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

一、模式概述

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、消息队列、事件驱动架构的核心思想

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


相关推荐
武藤一雄4 小时前
C# 设计模式大全(第一弹|7种)
microsoft·设计模式·微软·c#·.net·.netcore
Aloha_up6 小时前
常见设计模式简介
设计模式
砍光二叉树8 小时前
【设计模式】行为型-迭代器模式
设计模式·迭代器模式
Elaine3368 小时前
【Agent 设计模式全景图:从 ReAct 到工业级多智能体架构】
设计模式·llm·软件架构·ai agent
han_9 小时前
JavaScript设计模式(六):职责链模式实现与应用
前端·javascript·设计模式
无籽西瓜a10 小时前
【西瓜带你学设计模式 | 第三期-工厂方法模式】工厂方法模式——定义、实现方式、优缺点与适用场景以及注意事项
java·后端·设计模式·工厂方法模式
无籽西瓜a11 小时前
【西瓜带你学设计模式 | 第四期 - 抽象工厂模式】抽象工厂模式 —— 定义、核心结构、实战示例、优缺点与适用场景及模式区别
java·后端·设计模式·软件工程·抽象工厂模式
￰meteor12 小时前
23种设计模式 -【抽象工厂】
后端·设计模式
程序员小寒13 小时前
JavaScript设计模式(五):装饰者模式实现与应用
前端·javascript·设计模式