观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
// 观察者接口
class Observer {
update(news) {
throw new Error('Method not implemented');
}
}
// 具体观察者
class NewsSubscriber extends Observer {
#name;
constructor(name) {
super();
this.#name = name;
}
update(news) {
console.log(`${this.#name} received news: ${news}`);
}
}
// 主题(被观察者)
class NewsPublisher {
#observers = new Set();
#latestNews = '';
addObserver(observer) {
this.#observers.add(observer);
}
removeObserver(observer) {
this.#observers.delete(observer);
}
notifyObservers() {
for (const observer of this.#observers) {
observer.update(this.#latestNews);
}
}
setNews(news) {
this.#latestNews = news;
this.notifyObservers();
}
}
// 新闻类别(具体主题)
class SportsNewsPublisher extends NewsPublisher {
constructor() {
super();
this.category = 'Sports';
}
publishNews(news) {
console.log(`\nPublishing sports news: ${news}`);
this.setNews(`[Sports] ${news}`);
}
}
class TechnologyNewsPublisher extends NewsPublisher {
constructor() {
super();
this.category = 'Technology';
}
publishNews(news) {
console.log(`\nPublishing technology news: ${news}`);
this.setNews(`[Technology] ${news}`);
}
}
// 新闻订阅管理器
class NewsSubscriptionManager {
#publishers = new Map();
addPublisher(publisher) {
this.#publishers.set(publisher.category, publisher);
}
subscribe(subscriberName, category) {
const publisher = this.#publishers.get(category);
if (publisher) {
const subscriber = new NewsSubscriber(subscriberName);
publisher.addObserver(subscriber);
console.log(`${subscriberName} subscribed to ${category} news`);
} else {
console.log(`Category ${category} not available`);
}
}
publishNews(category, news) {
const publisher = this.#publishers.get(category);
if (publisher) {
publisher.publishNews(news);
} else {
console.log(`Cannot publish to ${category} - category not found`);
}
}
}
// 使用示例
function demonstrateObserver() {
const manager = new NewsSubscriptionManager();
const sportsPublisher = new SportsNewsPublisher();
const techPublisher = new TechnologyNewsPublisher();
manager.addPublisher(sportsPublisher);
manager.addPublisher(techPublisher);
manager.subscribe('Alice', 'Sports');
manager.subscribe('Bob', 'Technology');
manager.subscribe('Charlie', 'Sports');
manager.subscribe('Charlie', 'Technology');
manager.publishNews('Sports', 'Local team wins championship');
manager.publishNews('Technology', 'New AI breakthrough announced');
}
demonstrateObserver();
实现思路
-
Observer类:这是观察者接口,定义了update方法。 -
NewsSubscriber类(具体观察者):- 实现了
Observer接口。 - 使用私有字段
#name来存储订阅者名称。 - 实现了
update方法来处理接收到的新闻。
- 实现了
-
NewsPublisher类(抽象主题):- 使用私有字段
#observers(Set)来存储观察者。 - 提供了添加、移除和通知观察者的方法。
- 使用私有字段
#latestNews来存储最新新闻。
- 使用私有字段
-
SportsNewsPublisher和TechnologyNewsPublisher类(具体主题):- 继承自
NewsPublisher。 - 实现了特定类别的新闻发布逻辑。
- 继承自
-
NewsSubscriptionManager类:- 管理不同类别的新闻发布者。
- 提供订阅和发布新闻的高层方法。
优点
- 松耦合:主题和观察者之间是松耦合的,它们可以独立变化。
- 广播通信:支持一对多的通信模式。
- 动态关系:可以在运行时动态地建立对象之间的关系。
- 开闭原则:可以在不修改现有代码的情况下添加新的观察者。