观察者模式

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


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));
        }
    }
}
相关推荐
jingling5552 小时前
面试版-前端开发核心知识
开发语言·前端·javascript·vue.js·面试·前端框架
莫空00002 小时前
深入理解JavaScript属性描述符:从数据属性到存取器属性
前端·面试
wuxinyan1234 小时前
Java面试题033:一文深入了解MySQL(5)
java·数据库·mysql·面试
笑衬人心。4 小时前
HTTPS详解:原理 + 加解密过程 + 面试问答
java·网络协议·http·面试·https
欧阳有财4 小时前
[java八股文][Mysql面试篇]日志
java·mysql·面试
N_NAN_N5 小时前
类图+案例+代码详解:软件设计模式----原型模式
java·设计模式·原型模式
缘来是庄6 小时前
设计模式之组合模式
java·设计模式·组合模式
DKPT6 小时前
Java组合模式实现方式与测试方法
java·笔记·学习·设计模式·组合模式
鼠鼠我呀26 小时前
【设计模式09】组合模式
设计模式·组合模式
我是哪吒6 小时前
分布式微服务系统架构第155集:JavaPlus技术文档平台日更-Java线程池实现原理
后端·面试·github