设计模式-观察者模式

1. 核心角色与类结构

观察者模式包含 4 个核心角色,代码中对应如下:

  • 观察者接口(Observer):定义观察者接收通知的方法。
  • 主题接口(Subject):定义主题管理观察者、通知观察者的方法。
  • 具体主题(Concrete Subject)NewsAgency,维护状态,当状态变化时通知所有观察者。
  • 具体观察者(Concrete Observer)NewsChannel,依赖主题,接收通知并做出响应。
  • 使用示例(ObserverDemo):演示主题与观察者的交互流程。

2. 具体实现

(1)观察者接口(Observer)
复制代码
public interface Observer {
    void update(String message);
}
  • 定义了观察者的核心方法update,用于接收主题发送的通知(参数message为通知内容)。
  • 所有具体观察者(如NewsChannel)都必须实现此接口,确保主题能统一调用观察者的更新方法。
(2)主题接口(Subject)
复制代码
public interface Subject {
    void registerObserver(Observer observer);  // 注册观察者
    void removeObserver(Observer observer);    // 移除观察者
    void notifyObservers();                    // 通知所有观察者
}
  • 定义了主题对观察者的管理行为:
    • registerObserver:添加观察者到主题的 "观察者列表" 中。
    • removeObserver:从列表中移除观察者。
    • notifyObservers:当主题状态变化时,遍历列表并通知所有观察者。
  • 接口的作用是规范主题的行为,使具体主题(如NewsAgency)遵循统一的交互标准。
(3)具体主题(NewsAgency)
复制代码
public class NewsAgency implements Subject {
    // 存储所有注册的观察者(一对多关系的核心)
    private List<Observer> observers = new ArrayList<>();
    // 主题的状态(新闻内容)
    private String news;
    
    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);  // 新增观察者到列表
    }
    
    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);  // 从列表移除观察者
    }
    
    @Override
    public void notifyObservers() {
        // 遍历所有观察者,调用其update方法发送通知
        for (Observer observer : observers) {
            observer.update(news);
        }
    }
    
    // 对外提供的设置新闻的方法(状态变更的触发点)
    public void setNews(String news) {
        this.news = news;  // 更新自身状态
        notifyObservers(); // 状态变更后立即通知所有观察者
    }
}
  • 核心逻辑NewsAgency作为 "新闻 agency",维护一个观察者列表(如新闻频道),当新闻内容(状态)更新时,主动通知所有注册的观察者。
  • 状态与通知的绑定setNews方法是关键,它在更新news属性后,立即调用notifyObservers,确保状态变化能被观察者感知。
(4)具体观察者(NewsChannel)
复制代码
public class NewsChannel implements Observer {
    // 观察者自身存储的新闻(与主题同步的状态)
    private String news;
    
    @Override
    public void update(String news) {
        this.news = news;  // 接收主题的通知,更新自身状态
        display();         // 状态更新后执行展示逻辑
    }
    
    // 展示收到的新闻
    public void display() {
        System.out.println("收到新闻: " + news);
    }
}
  • 实现Observer接口,通过update方法接收主题(NewsAgency)的通知,并更新自身存储的新闻内容。
  • display方法是观察者收到通知后的具体响应(这里是打印新闻),实际场景中可以是更复杂的逻辑(如刷新 UI、存储数据库等)。
(5)使用示例(ObserverDemo)
复制代码
public class ObserverDemo {
    public static void main(String[] args) {
        // 1. 创建主题(新闻 agency)
        NewsAgency agency = new NewsAgency();
        // 2. 创建观察者(新闻频道)
        NewsChannel channel1 = new NewsChannel();
        NewsChannel channel2 = new NewsChannel();
        
        // 3. 注册观察者(频道订阅 agency)
        agency.registerObserver(channel1);
        agency.registerObserver(channel2);
        
        // 4. 主题状态变更(发布新闻),自动通知所有观察者
        agency.setNews("重大新闻:设计模式很重要!");
    }
}
  • 执行流程

    1. 创建NewsAgency(主题)和两个NewsChannel(观察者)。
    2. 两个频道通过registerObserver订阅 agency 的新闻。
    3. 调用agency.setNews发布新闻,此时 agency 自动调用notifyObservers,触发所有订阅的频道执行update方法。
  • 输出结果

    plaintext

    复制代码
    收到新闻: 重大新闻:设计模式很重要!
    收到新闻: 重大新闻:设计模式很重要!

    (两个频道都收到了新闻通知)

3. 观察者模式的核心优势

  • 松耦合 :主题与观察者之间通过接口交互,双方无需知道对方的具体实现。例如,NewsAgency不需要知道观察者是NewsChannel还是其他类,只要它实现了Observer接口即可。
  • 自动通知:当主题状态变化时,所有依赖它的观察者会被自动通知,无需手动逐个调用,减少了代码冗余。
  • 动态扩展 :可以随时添加或移除观察者(如新增NewsChannel3并注册),不影响主题和其他观察者的逻辑,符合 "开闭原则"。

总结

以上代码通过观察者模式实现了 "新闻 agency 发布新闻,多个新闻频道自动接收并展示" 的场景。核心是主题维护观察者列表,状态变化时主动通知所有观察者,从而实现对象间的灵活通信。该模式在实际开发中应用广泛,例如 GUI 事件监听、消息订阅系统、状态同步等场景。

相关推荐
安冬的码畜日常2 天前
【JUnit实战3_27】第十六章:用 JUnit 测试 Spring 应用:通过实战案例深入理解 IoC 原理
spring·观察者模式·设计模式·单元测试·ioc·依赖注入·junit5
czy87874752 天前
C语言实现观察者模式
c语言·观察者模式
Miqiuha12 天前
观察者模式学习
学习·观察者模式
金宗汉19 天前
《宇宙递归拓扑学:基于自指性与拓扑流形的无限逼近模型》
大数据·人工智能·笔记·算法·观察者模式
kyle~20 天前
设计模式---观察者模式
服务器·观察者模式·设计模式
Mr_WangAndy21 天前
C++设计模式_行为型模式_观察者模式Observer(发布-订阅(Publish-Subscribe))
c++·观察者模式·设计模式
o0向阳而生0o1 个月前
107、23种设计模式之观察者模式(16/23)
观察者模式·设计模式
青草地溪水旁1 个月前
设计模式(C++)详解——观察者模式(Observer)(1)
c++·观察者模式·设计模式
星空寻流年1 个月前
设计模式第六章(观察者模式)
网络·观察者模式·设计模式