观察者模式

点击阅读:设计模式系列文章


1. 观察者模式的定义

观察者模式 (Observer Pattern)是一种行为设计模式 ,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

观察者模式所做的工作就是在解除耦合。使耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。

观察者模式解决了以下关键问题:

  • 状态同步难题:当多个对象需要同步状态时,避免硬编码的依赖关系
  • 动态订阅机制:运行时动态添加/移除观察者的能力
  • 事件驱动架构:构建响应式系统的基石

2. 观察者模式的结构

  1. Subject:抽象主题,一般为抽象类或接口,将所有的观察者引用存在一个集合里,并提供了增加和删除观察者对象的接口。
java 复制代码
public abstract class Subject {
    private List<Observer> observers = new ArrayList<>();
    

    private String state;
    
    public void setState(String state) {
        this.state = state;
        notifyObservers(); // 状态变更时通知观察者
    }
    
    public String getSubjectState(){
        return subjectState;
    }
    
    //添加观察者
    public void attach(Observer observer) {
        observers.add(observer);
    }

    //删除观察者
    public void detach(Observer observer) {
        observers.remove(observer);
    }

    //通知所有观察者
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}
  1. ConcreteSubject:具体主题,将有关联状态存入具体观察者对象。在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
java 复制代码
public class ConcreteSubject extends Subject {

}
  1. Observer:抽象观察者,一般为抽象类或接口,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
java 复制代码
public interface Observer {
    void update();
}
  1. ConcreteObserver:具体观察者,实现具体观察者所要求的更新接口,以便使本身的状态与主题的状态相协调。
java 复制代码
public class ConcreteObserver implements Observer {
    private String name;
    private String subjectState;
    private Subject subject;

    public ConcreteObserver(String name, ConcreteSubject subject) {
        this.name = name;
        this.subject = subject;
    }

    @Override
    public void update() {
        subjectState = subject.getSubjectState();
        System.out.println("ConcreteObserver", "Observer " + name + ", state " + subjectState);
    }
}
  1. 客户端代码
java 复制代码
Subject subject = new ConcreteSubject();
subject.attach(new ConcreteObserver("Zhang San", subject));
subject.attach(new ConcreteObserver("Li Si", subject));
subject.attach(new ConcreteObserver("Wang Wu", subject));
subject.setSubjectState("Change");

3. 观察者模式 Java 内置接口的实现

Java 已经为观察者模式准备好了相关的接口和抽象类了。

java 复制代码
// 继承Observable类
class WeatherStation extends Observable {
    private float temperature;
    
    public void setTemperature(float temp) {
        this.temperature = temp;
        setChanged(); // 标记状态已改变
        notifyObservers(); // 通知观察者
    }
}

// 实现Observer接口
class PhoneDisplay implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof WeatherStation) {
            System.out.println("");
        }
    }
}

// 使用示例
WeatherStation station = new WeatherStation();
station.addObserver(new PhoneDisplay());
station.setTemperature(25.5f);

4. 观察者模式的优缺点

优点 :

  • 解耦设计:主题和观察者之间保持最小依赖
  • 动态扩展:无需修改主题即可增加新观察者
  • 事件驱动:支持分布式事件处理系统
  • 重用性高:主题和观察者可以独立复用

缺点 :

  • 通知顺序不可控:观察者接收通知的顺序不确定
  • 性能问题:大量观察者可能导致通知过程耗时
  • 循环依赖风险:不当实现可能导致循环调用

5. 观察者模式的相关实践

5.1 推拉模型

  • 推模型:主题主动将详细数据发送给观察者
  • 拉模型:观察者收到通知后主动从主题获取数据
java 复制代码
// 推模型实现
protected void notifyObservers(Object data) {
    for (Observer o : observers) {
        o.update(data); // 直接传递数据
    }
}

// 拉模型实现(推荐)
protected void notifyObservers() {
    for (Observer o : observers) {
        o.update(this); // 传递主题引用
    }
}

5.2 异步通知机制

线程安全优化,避免阻塞主题线程:

java 复制代码
public class ConcurrentSubject {
    private final CopyOnWriteArrayList<Observer> observers = 
        new CopyOnWriteArrayList<>();
    
    public void notifyObservers() {
        for (Observer o : observers) {
            // 使用线程池异步处理
            executorService.submit(() -> o.update(this));
        }
    }
}
相关推荐
进击的野人3 小时前
CSS选择器与层叠机制
css·面试
T___T6 小时前
全方位解释 JavaScript 执行机制(从底层到实战)
前端·面试
9号达人6 小时前
普通公司对账系统的现实困境与解决方案
java·后端·面试
勤劳打代码7 小时前
条分缕析 —— 通过 Demo 深入浅出 Provider 原理
flutter·面试·dart
努力学算法的蒟蒻7 小时前
day10(11.7)——leetcode面试经典150
面试
进击的野人8 小时前
JavaScript 中的数组映射方法与面向对象特性深度解析
javascript·面试
南山安8 小时前
以腾讯面试题深度剖析JavaScript:从数组map方法到面向对象本质
javascript·面试
王道长服务器 | 亚马逊云9 小时前
AWS + 苹果CMS:影视站建站的高效组合方案
服务器·数据库·搜索引擎·设计模式·云计算·aws
橘颂TA9 小时前
【剑斩OFFER】算法的暴力美学——二分查找
算法·leetcode·面试·职场和发展·c/c++
在未来等你10 小时前
AI Agent设计模式 Day 1:ReAct模式:推理与行动的完美结合
设计模式·llm·react·ai agent·plan-and-execute