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("重大新闻:设计模式很重要!");
}
}
-
执行流程 :
- 创建
NewsAgency(主题)和两个NewsChannel(观察者)。 - 两个频道通过
registerObserver订阅 agency 的新闻。 - 调用
agency.setNews发布新闻,此时 agency 自动调用notifyObservers,触发所有订阅的频道执行update方法。
- 创建
-
输出结果 :
plaintext
收到新闻: 重大新闻:设计模式很重要! 收到新闻: 重大新闻:设计模式很重要!(两个频道都收到了新闻通知)
3. 观察者模式的核心优势
- 松耦合 :主题与观察者之间通过接口交互,双方无需知道对方的具体实现。例如,
NewsAgency不需要知道观察者是NewsChannel还是其他类,只要它实现了Observer接口即可。 - 自动通知:当主题状态变化时,所有依赖它的观察者会被自动通知,无需手动逐个调用,减少了代码冗余。
- 动态扩展 :可以随时添加或移除观察者(如新增
NewsChannel3并注册),不影响主题和其他观察者的逻辑,符合 "开闭原则"。
总结
以上代码通过观察者模式实现了 "新闻 agency 发布新闻,多个新闻频道自动接收并展示" 的场景。核心是主题维护观察者列表,状态变化时主动通知所有观察者,从而实现对象间的灵活通信。该模式在实际开发中应用广泛,例如 GUI 事件监听、消息订阅系统、状态同步等场景。