用JavaScript实现观察者模式
- 观察者模式定义:是一种行为设计模式,定义了一对多的依赖关系,主题对象状态变化时会通知所有观察者对象,使其自动更新。
- JavaScript 实现示例
- 主题类(Subject):维护观察者数组,提供添加(
addObserver
)、移除(removeObserver
)和通知(notifyObservers
)观察者的方法。 - 观察者类(Observer):定义
update
方法,在接收到通知时被调用。 - 使用示例:创建
Subject
和Observer
实例,添加观察者,通知观察者,移除观察者后再次通知,展示了观察者模式的基本流程。
- 主题类(Subject):维护观察者数组,提供添加(
- 优缺点
- 优点:解耦观察者和被观察者;支持运行时动态添加或移除观察者;实现广播通信;是事件驱动架构的基础;可支持多种观察者。
- 缺点:大量观察者时通知可能导致性能下降;存在循环依赖风险;缺乏变化细节,增加实现复杂性。
- 实际应用场景
- GUI 事件监听:如 Web 开发中的 DOM 事件监听,按钮点击等事件处理。
- 数据模型与视图同步:在 MVC 架构及 Vue.js、React 等框架中,实现数据模型变化时视图自动更新。
- 发布 - 订阅系统:消息中间件(如 Kafka、RabbitMQ)和社交媒体平台采用该机制,发布者发布消息,订阅者接收通知处理。
- 金融系统监控:股票市场监控系统中,投资者作为观察者订阅股票,股价变动时接收通知决策。
- 缓存系统的失效通知:分布式系统中,缓存数据失效时通知相关系统或服务更新或重新加载数据。
示例:
- 简单的事件发布 - 订阅系统
// 定义一个主题类(Subject)
class Subject {
constructor() {
this.observers = [];
}
// 添加观察者
addObserver(observer) {
this.observers.push(observer);
}
// 移除观察者
removeObserver(observer) {
const index = this.observers.indexOf(observer);
if (index > -1) {
this.observers.splice(index, 1);
}
}
// 通知所有观察者
notifyObservers(data) {
this.observers.forEach(observer => observer.update(data));
}
}
// 定义一个观察者类(Observer)
class Observer {
constructor(name) {
this.name = name;
}
// 更新方法,在接收到通知时调用
update(data) {
console.log(`${this.name} received data: ${data}`);
}
}
// 使用示例
const subject = new Subject();
const observer1 = new Observer('Observer 1');
const observer2 = new Observer('Observer 2');
subject.addObserver(observer1);
subject.addObserver(observer2);
// 通知观察者
subject.notifyObservers('Hello Observers!');
// 移除一个观察者
subject.removeObserver(observer1);
// 再次通知观察者(此时只通知 observer2)
subject.notifyObservers('Hello Remaining Observer!');
在这个示例中,Publisher
类充当主题角色,subscribe
、unsubscribe
和publish
方法分别用于管理订阅者、取消订阅和发布事件通知订阅者。
2. 模拟游戏角色状态变化通知
// 游戏角色类(被观察者)
class GameCharacter {
constructor(name) {
this.name = name;
this.health = 100;
this.observers = [];
}
// 添加观察者
addObserver(observer) {
this.observers.push(observer);
}
// 移除观察者
removeObserver(observer) {
const index = this.observers.indexOf(observer);
if (index > -1) {
this.observers.splice(index, 1);
}
}
// 通知观察者
notifyObservers() {
this.observers.forEach(observer => observer.update(this.name, this.health));
}
// 受到伤害方法
takeDamage(damage) {
this.health -= damage;
console.log(`${this.name} 受到 ${damage} 点伤害,剩余生命值: ${this.health}`);
this.notifyObservers();
}
}
// 观察者类
class CharacterObserver {
constructor(name) {
this.name = name;
}
// 更新方法
update(characterName, health) {
console.log(`${this.name} 观察到 ${characterName} 的生命值变为: ${health}`);
}
}
// 使用示例
const character = new GameCharacter('战士');
const observer1 = new CharacterObserver('玩家1');
const observer2 = new CharacterObserver('玩家2');
character.addObserver(observer1);
character.addObserver(observer2);
character.takeDamage(20);
character.removeObserver(observer1);
character.takeDamage(10);
该示例中,GameCharacter
类表示游戏角色,当角色受到伤害时会通知所有观察者,展示了观察者模式在游戏开发中角色状态监控方面的应用。