观察者模式
观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个目标对象。当这个目标对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新。
基本概念
在观察者模式中,有两个主要角色:
目标(Subject):也叫做被观察者或可观察者(Observable)
- 维护一组观察者
- 提供添加和移除观察者的方法
- 当状态改变时通知所有观察者
观察者(Observer):
- 定义一个更新接口,在目标状态改变时更新自己
代码实现
ts
import dayjs from "dayjs";
import { ref } from "vue";
interface ILog {
name: string;
date: string;
message: string;
}
const logs = ref<ILog[]>([]);
/**
* 观察者
* 观察者有一个方法,
* 1. 更新信息 update(message)
* @class Observer
* @description 一个简单的观察者
* */
class Observer {
constructor(public name: string) {}
/**
* 给观察者发送消息
* @param message {string}
* @returns {void}
*/
update(message: string): void {
logs.value.push({
name: this.name,
date: dayjs().format("YYYY-MM-DD HH:mm:ss"),
message: message,
});
}
}
/**
* 订阅者
* 订阅者有三个方法
* 1. 订阅 attach(observer: Observer)
* 2. 取消订阅 detach(observer: Observer)
* 3. 通知观察者消息 notify(message: string)
*
* @class Subject
* @description 一个简单的被观察者
*/
class Subject {
private observers: Set<Observer> = new Set();
constructor() {}
/**
* 添加观察者
* @param observer {Observer}
* @returns {void}
*/
attach(observer: Observer): void {
this.observers.add(observer);
}
/**
* 移除观察者
* @param observer {Observer}
* @returns {void}
*/
detach(observer: Observer): void {
this.observers.delete(observer);
}
/**
* 通知观察者消息
* @param message {string}
*/
notify(message: string): void {
this.observers.forEach((observer) => observer.update(message));
}
}
export { Observer, Subject, logs };
实际应用场景
事件处理系统
javascript// DOM 事件就是一个典型的观察者模式 element.addEventListener("click", () => { console.log("点击事件触发"); });
状态管理
javascript// Vue 的响应式系统 const state = Vue.reactive({ count: 0 }); // 当 state.count 改变时,视图会自动更新
消息订阅系统
javascript// 发布订阅模式(观察者模式的变体) const eventBus = { events: {}, subscribe(event, callback) { if (!this.events[event]) { this.events[event] = []; } this.events[event].push(callback); }, publish(event, data) { if (this.events[event]) { this.events[event].forEach(callback => callback(data)); } } };
优缺点
优点
- 符合开闭原则,易于扩展
- 可以在运行时建立对象之间的关系
- 支持广播通信
缺点
- 观察者过多时可能会影响性能
- 可能会导致循环依赖
- 观察者之间的依赖关系不易跟踪和维护
最佳实践
合理使用解耦:观察者模式主要用于解耦,但不是所有的场景都需要使用它。
避免过度使用:过多的观察者会导致系统难以维护和调试。
注意内存泄漏:记得在适当的时候移除观察者,特别是在处理 DOM 事件时。
错误处理:在通知观察者时要做好错误处理,防止一个观察者的错误影响到其他观察者。
javascript
notify(message) {
this.observers.forEach(observer => {
try {
observer.update(message);
} catch (error) {
console.error(`通知观察者失败:`, error);
}
});
}
示例内容
主题管理
观察者管理
已添加的观察者
默认观察者
日志输出
[2024-12-29 18:14:45][默认观察者]不要惊讶,这是一个默认消息