我就是奇迹

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

观察者模式(Observer Pattern)

意图 

定义对象间的一种 “一对多” 依赖关系,当一个对象(被观察者)的状态发生变化时,所有依赖它的对象(观察者)都会收到通知,并自动更新。

 


 

主要解决

需要在多个对象之间建立联动机制,保证数据同步状态一致性

降低耦合度,让对象之间的关系不需要直接引用,而是通过事件通知机制实现解耦。

 


 

何时使用

适用于以下场景:

1. 数据变化需要通知多个模块(如:GUI 事件、订阅-发布模式)

2. 对象之间存在依赖关系(如:MVC 设计模式)

3. 希望实现松耦合的消息传递机制(如:消息队列、事件驱动架构)

 


 

结构

 

观察者模式通常由以下组件组成:

1. Subject(被观察者):维护观察者列表,当自身状态发生变化时,通知所有观察者。

2. Observer(观察者):定义 update() 方法,当 Subject 发生变化时执行更新操作。

3. ConcreteSubject(具体被观察者):具体的业务对象,状态发生变化时调用 notifyObservers()。

4. ConcreteObserver(具体观察者):接收通知并执行相应操作。

 


 

类图

 


 

示例代码(Java 实现)

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

// 观察者接口
interface Observer {
    void update(String message);
}

// 被观察者(Subject)
class Subject {
    private List<Observer> observers = new ArrayList<>();

    // 订阅观察者
    public void attach(Observer observer) {
        observers.add(observer);
    }

    // 取消订阅
    public void detach(Observer observer) {
        observers.remove(observer);
    }

    // 通知所有观察者
    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

// 具体观察者A
class ConcreteObserverA implements Observer {
    private String name;

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

    @Override
    public void update(String message) {
        System.out.println(name + " 收到通知: " + message);
    }
}

// 具体观察者B
class ConcreteObserverB implements Observer {
    private String name;

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

    @Override
    public void update(String message) {
        System.out.println(name + " 收到通知: " + message);
    }
}

// 测试代码
public class ObserverPatternDemo {
    public static void main(String[] args) {
        Subject subject = new Subject();

        Observer observer1 = new ConcreteObserverA("观察者1");
        Observer observer2 = new ConcreteObserverB("观察者2");

        subject.attach(observer1);
        subject.attach(observer2);

        System.out.println("被观察者状态改变,发送通知...");
        subject.notifyObservers("状态已更新!");
    }
}

 

 


 

输出结果

被观察者状态改变,发送通知...
观察者1 收到通知: 状态已更新!
观察者2 收到通知: 状态已更新!

 

 


 

优缺点

 

✅ 优点

1. 解耦合 —— 观察者和被观察者独立,不直接依赖彼此的具体实现。

2. 支持动态变化 —— 可以在运行时添加或移除观察者,提高灵活性。

3. 自动通知 —— 任何状态变化都会自动触发通知,避免手动检查状态的复杂性。

 

❌ 缺点

1. 通知机制可能引发性能问题 —— 如果观察者过多,或者更新逻辑复杂,可能导致广播通知的性能问题。

2. 难以控制通知顺序 —— 观察者的执行顺序通常不可控,在某些情况下可能导致不一致性。

3. 可能导致循环依赖 —— 需要谨慎设计,避免观察者又影响被观察者,形成死循环。

 


 

应用场景

 

场景

示例

GUI 事件驱动

按钮点击事件、窗口变化等

消息推送系统

订阅-发布模式,如微信公众号推送

模型-视图-控制器(MVC)

视图监听模型数据的变化

股票市场

交易系统实时通知股价变化

游戏开发

玩家状态改变时通知多个 UI 组件

 

 


 

变体与扩展

Java 内置 Observer 模式:Java 提供了 Observable 类和 Observer 接口,可以直接使用。

事件驱动架构(Event-Driven Architecture):类似 EventBus 机制,允许更灵活的事件分发。

Reactive Programming(响应式编程):如 RxJava,观察者模式的升级版,支持异步流数据处理。

 


 

总结

1. 观察者模式用于一对多的依赖关系,让多个对象在目标对象状态变化时自动收到通知。

2. 核心思想是“订阅-通知”机制,使观察者和被观察者解耦,提高灵活性。

3. 适用于 GUI 事件、消息推送、数据联动等场景,但要注意性能和依赖管理。

posted on 2025-04-01 16:12  我就是奇迹  阅读(54)  评论(0)    收藏  举报