「八卦传播者」—— 观察者模式

文章目录

示例代码

示例代码

完整代码

复制代码
src/
├── common/                          # 共享接口包
│   ├── Observer.java                # Observer:观察者接口
│   └── Subject.java                 # Subject:主题接口
│
└── observer/                        # 观察者实现
    ├── ConcreteSubject.java         # Concrete Subject:具体主题
    ├── UserObserver.java            # Concrete Observer:具体观察者
    ├── NewsAgencyClient.java        # Client:客户端
    └── ObserverDemo.java           # 运行入口

编译运行

bash 复制代码
# 编译
javac -d out src/common/*.java src/observer/*.java

# 运行
java -cp out observer.ObserverDemo

什么是观察者模式?

概念

观察者模式 是一种行为型设计模式,它的核心作用是定义对象之间的一对多依赖关系,当一个对象(主题)的状态发生改变时,所有依赖它的观察者都会自动收到通知并更新

简单来说,观察者模式就是在发布-订阅

生活类比

就像报纸订阅:

  • 报社(Subject)每天出版报纸
  • 订阅者(Observer)收到通知
  • 当有新技术发布时,所有订阅者都会收到通知

在代码世界中,观察者模式干的是同样的事:

  • 主题维护观察者列表
  • 当主题状态改变,通知所有观察者
  • 观察者和主题之间是松耦合关系

观察者模式中的三个角色

Subject(主题)

维护观察者列表,并在状态改变时通知观察者。在我们的例子中是 Subject

java 复制代码
// src/common/Subject.java
package common;

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

public abstract class Subject {
    protected List<Observer> observers = new ArrayList<>();

    public void attach(Observer observer) {
        observers.add(observer);
    }

    public void detach(Observer observer) {
        observers.remove(observer);
    }

    public void notifyAllObservers() {
        for (Observer observer : observers) {
            observer.update(getMessage());
        }
    }

    public abstract String getMessage();
}

Observer(观察者)

定义收到通知时的更新接口。在我们的例子中是 Observer

java 复制代码
// src/common/Observer.java
package common;

public interface Observer {
    void update(String message);
}

ConcreteSubject(具体主题)

存储真实状态,当状态改变时通知观察者。在我们的例子中是 ConcreteSubject

java 复制代码
// src/observer/ConcreteSubject.java
package observer;

import common.Subject;

public class ConcreteSubject extends Subject {
    private String message;

    public void setMessage(String message) {
        this.message = message;
        System.out.println("  [Subject] 发布新消息: " + message);
        notifyAllObservers();
    }

    @Override
    public String getMessage() {
        return message;
    }
}

ConcreteObserver(具体观察者)

实现 Observer 接口的具体类。在我们的例子中是 UserObserver

java 复制代码
// src/observer/UserObserver.java
package observer;

import common.Observer;

public class UserObserver implements Observer {
    private String name;

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

    @Override
    public void update(String message) {
        System.out.println("  [" + name + "] 收到更新: " + message);
    }
}

观察者模式示例

结构图

复制代码
┌─────────────┐       ┌──────────────┐
│   Subject   │◄──────│   Observer   │
│ (主题)      │ notify│  (观察者)     │
└─────────────┘       └──────────────┘
       ▲                    ▲
       │                    │
       │                    │
┌─────────────┐       ┌──────────────┐
│ConcreteSubject│      │UserObserver │
│ (具体主题)   │       │ (具体观察者) │
└─────────────┘       └──────────────┘

运行示例

复制代码
>>> 初始化新闻主题

>>> 用户订阅
  [Client] 用户 '张三' 订阅了新闻
  [Client] 用户 '李四' 订阅了新闻
  [Client] 用户 '王五' 订阅了新闻

>>> 发布第一条新闻:突发!某地发生地震
  [Subject] 发布新消息: 突发!某地发生地震
  [张三] 收到更新: 突发!某地发生地震
  [李四] 收到更新: 突发!某地发生地震
  [王五] 收到更新: 突发!某地发生地震

>>> 用户王五退订

>>> 发布第二条新闻:天气预报:明天有雨
  [Subject] 发布新消息: 天气预报:明天有雨
  [张三] 收到更新: 天气预报:明天有雨
  [李四] 收到更新: 天气预报:明天有雨

代码实现

java 复制代码
// 创建主题
Subject news = new ConcreteSubject();

// 订阅
news.attach(new UserObserver("张三"));
news.attach(new UserObserver("李四"));
news.attach(new UserObserver("王五"));

// 发布消息
((ConcreteSubject) news).setMessage("突发!某地发生地震");

// 退订
news.detach(observers.get("王五"));

// 再次发布
((ConcreteSubject) news).setMessage("天气预报:明天有雨");

观察者模式的优势

  1. 松耦合:主题和观察者之间不直接依赖
  2. 动态交互:可以在运行时动态添加/移除观察者
  3. 开闭原则:对扩展开放,不需要修改主题代码
  4. 一对多关系:一个主题可以对应多个观察者

观察者模式的注意事项

  1. 通知顺序:观察者收到通知的顺序是不确定的
  2. 循环依赖:避免观察者和主题之间的循环依赖
  3. 通知效率:观察者数量过多时,通知可能影响性能
相关推荐
多加点辣也没关系12 小时前
设计模式-观察者模式
观察者模式·设计模式
heimeiyingwang13 天前
【架构实战】状态机架构:订单/工单状态流转设计
观察者模式·架构·wpf
heimeiyingwang18 天前
【架构实战】观察者模式在分布式系统中的应用
观察者模式·架构·wpf
geovindu18 天前
go: Observer Pattern
开发语言·观察者模式·设计模式·golang
工业甲酰苯胺22 天前
Tomcat的事件监听机制:观察者模式
java·观察者模式·tomcat
ximu_polaris22 天前
设计模式(C++)-行为型模式-观察者模式
c++·观察者模式·设计模式
悟05151 个月前
观察者模式
观察者模式
一颗青果1 个月前
观察者模式讲解
观察者模式
yaaakaaang1 个月前
十九、观察者模式
java·观察者模式