温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

怎么用观察者模式解耦

发布时间:2026-07-18 15:38:46 来源:亿速云 阅读:91 作者:小樊 栏目:编程语言

观察者模式(Observer Pattern)是一种行为型设计模式,核心思想是:

“一个对象状态发生变化时,自动通知所有依赖它的对象,而不需要这些对象与之紧耦合。”

下面我从 为什么、是什么、怎么做、代码示例、常见误区 几个方面讲清楚如何用观察者模式解耦


一、为什么需要解耦?

假设你有一个订单系统:

下单成功 → 发短信
         → 发邮件
         → 更新库存
         → 记录日志

❌ 传统写法(耦合严重):

class OrderService {
    public void createOrder() {
        // 下单
        sendSMS();
        sendEmail();
        updateInventory();
        log();
    }
}

问题:

  • 每新增一个操作,就要改 OrderService
  • OrderService 知道太多“下游细节”
  • 违反 单一职责原则 + 开闭原则

二、观察者模式如何解耦?

核心思路:

  • ✅ 发布者(Subject)只负责发布事件
  • ✅ 订阅者(Observer)只关心自己要处理的事件
  • ✅ 它们之间通过“订阅关系”连接,而不是直接调用

三、观察者模式的结构

1️⃣ 角色说明

角色 作用
Subject(被观察者) 维护观察者列表,状态变化时通知
Observer(观察者) 定义响应接口
ConcreteSubject 具体被观察者
ConcreteObserver 具体观察者

四、一个经典示例(Java)

1️⃣ 观察者接口

public interface Observer {
    void onOrderCreated(String orderId);
}

2️⃣ 被观察者(Subject)

import java.util.ArrayList;
import java.util.List;

public class OrderSubject {

    private final List<Observer> observers = new ArrayList<>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    public void notifyObservers(String orderId) {
        for (Observer observer : observers) {
            observer.onOrderCreated(orderId);
        }
    }
}

3️⃣ 具体观察者

public class EmailObserver implements Observer {
    @Override
    public void onOrderCreated(String orderId) {
        System.out.println("发送邮件,订单:" + orderId);
    }
}
public class SmsObserver implements Observer {
    @Override
    public void onOrderCreated(String orderId) {
        System.out.println("发送短信,订单:" + orderId);
    }
}

4️⃣ 业务代码(解耦后)

public class OrderService {

    private final OrderSubject subject;

    public OrderService(OrderSubject subject) {
        this.subject = subject;
    }

    public void createOrder() {
        String orderId = "123";
        System.out.println("订单创建成功");

        // 只管通知
        subject.notifyObservers(orderId);
    }
}

5️⃣ 使用方式

public class Main {
    public static void main(String[] args) {
        OrderSubject subject = new OrderSubject();
        subject.addObserver(new EmailObserver());
        subject.addObserver(new SmsObserver());

        OrderService service = new OrderService(subject);
        service.createOrder();
    }
}

OrderService 不再关心谁要处理订单事件


五、用“事件机制”的现代写法(更推荐)

如果你用的是 Spring / 前端 / 后端框架,观察者模式通常直接叫 事件驱动 / 发布订阅

Spring 示例(最佳实践)

1️⃣ 定义事件

public class OrderCreatedEvent {
    private final String orderId;

    public OrderCreatedEvent(String orderId) {
        this.orderId = orderId;
    }

    public String getOrderId() {
        return orderId;
    }
}

2️⃣ 发布事件

@Service
public class OrderService {

    @Autowired
    private ApplicationEventPublisher publisher;

    public void createOrder() {
        String orderId = "123";
        publisher.publishEvent(new OrderCreatedEvent(orderId));
    }
}

3️⃣ 监听事件(观察者)

@Component
public class EmailListener {

    @EventListener
    public void handle(OrderCreatedEvent event) {
        System.out.println("发送邮件:" + event.getOrderId());
    }
}

完全解耦可扩展符合企业级架构


六、观察者模式解耦的本质

对比 耦合写法 观察者模式
调用方式 直接调用 事件通知
依赖方向 强依赖 只依赖接口
扩展性 改代码 加观察者
可测试性

七、常见误区 ❌

❌ 1. 观察者里写业务主流程

观察者只做“副作用”,不控制主流程

❌ 2. 观察者之间互相依赖

观察者必须彼此无感知

❌ 3. 观察者太多导致性能问题

可改为异步 / 消息队列


八、什么时候用观察者模式?

✅ 适合:

  • 状态变化需要触发多个行为
  • 事件驱动架构
  • 消息通知 / 审计 / 日志 / 缓存失效

❌ 不适合:

  • 强顺序、强一致性流程
  • 简单系统(过度设计)

如果你愿意,我可以:

  • ✅ 用 前端(JS / Vue / React) 讲观察者
  • ✅ 用 消息队列(Kafka / MQ) 对比观察者
  • ✅ 用 真实业务案例(支付 / 下单 / 审核) 拆解

你更想用在哪一块?

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI