1.  什么是观察者模式

观察者模式(Observer Pattern)是一种 行为型设计模式,用于建立对象之间的 一对多依赖关系,当一个对象(Subject,主题/被观察者)状态改变时,所有依赖它的对象(Observers,观察者)会自动收到通知并更新。

2.  优点和缺点

✅ 优点

1. 松耦合(Low Coupling)
  • 主题(Subject) 和 观察者(Observer) 之间仅通过抽象接口交互,彼此不知道具体实现。

  • 符合 依赖倒置原则(DIP),依赖抽象而非具体实现。

2. 动态订阅机制
  • 观察者可以 运行时动态注册/注销,灵活性高。

  • 例如:GUI 按钮可以随时添加或移除点击事件监听器。

3. 一对多通信
  • 一个主题状态变化可自动通知 多个观察者,无需手动遍历调用。

  • 适用于广播场景(如股票价格变动通知多个交易终端)。

4. 开闭原则支持
  • 新增观察者无需修改主题代码(只需注册)。

  • 扩展性强,适合需求频繁变化的系统。


❌ 缺点

1. 意外更新(Unintended Updates)
  • 观察者可能收到 不必要或冗余的通知(如主题频繁触发但状态未实际变化)。

  • 解决方案:引入 dirty 标志或差分通知(仅发送变化部分)。

2. 性能问题
  • 观察者数量多时,遍历通知所有观察者 可能成为性能瓶颈。

  • 解决方案:异步通知(如用线程池)或按优先级分批通知。

3. 内存泄漏风险
  • 如果观察者未正确注销,主题会持有观察者的引用,导致 对象无法被垃圾回收

  • 解决方案:使用弱引用(WeakReference)或显式注销机制。

4. 调试困难
  • 通知链可能形成 复杂的调用路径,导致问题难以追踪。

  • 解决方案:添加日志或使用事件总线(如 EventBus)管理流程。

3.  应用场景

场景 说明
GUI 事件处理 按钮点击、键盘输入等事件监听。
发布-订阅系统 Kafka、Redis Pub/Sub 等消息队列。
MVC 架构 模型(Model)变更时自动更新视图(View)。
游戏开发 角色血量变化触发 UI、音效、成就系统等多方响应

4. Java代码示例

// 主题接口
public interface Subject {
    /**
     * 注册一个观察者
     */
    void registerObserver(Observer observer);

    /**
     * 移除一个观察者
     */
    void removeObserver(Observer observer);

    /**
     * 通知所有观察者
     */
    void notifyObservers();

}

//观察者接口
public interface Observer {
   void update(String name,String age,String number);
}
//主题实现类

public class School implements Subject{
    private String name;
    private String age;
    private String number;

    private List<Observer> school;

    public School(){
        school = new CopyOnWriteArrayList<>();
    }


    @Override
    public void registerObserver(Observer o) {
        school.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        school.remove(o);
    }

    @Override
    public void notifyObserver() {
        for (Observer observer : school) {
            observer.update(name,age,number);
        }
    }

    public void setSchool(String name,String age,String number){
        this.name = name;
        this.age = age;
        this.number = number;
        notifyObserver();
    }
}
//观察者实现类

public class Display implements Observer{
    private String name;
    private String age;
    private String number;

    private Subject school;


    public Display(Subject school){
        this.school = school;
        school.registerObserver(this);
    }

    @Override
    public void update(String name, String age, String number) {
        this.name = name;
        this.age = age;
        this.number = number;
        display();
    }

    private void display() {
        System.out.println("姓名:"+name+",年龄:"+age+",工号:"+number);
    }
}
//测试
public static void main(String[] args) {
        School school = new School();
        Display display = new Display(school);
        school.setSchool("张三","22","n1");
        school.setSchool("张三","23","n2");
        school.setSchool("张三","24","n3");
    }

运行结果

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐