观察者模式(Observer Pattern)
约 1093 字大约 4 分钟
观察者模式:让对象之间"订阅"与"通知"
什么是观察者模式?
观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象发生变化时,它的所有依赖者(观察者)都会收到通知并自动更新。
简单来说,观察者模式就像是一个"订阅-发布"系统:
- 主题(Subject):负责维护观察者列表,并在状态变化时通知所有观察者
- 观察者(Observer):订阅主题,并在收到通知时更新自己的状态
生活中的例子
想象一下你订阅了一个YouTube频道:
- YouTube频道就是主题(Subject)
- 你就是观察者(Observer)
- 当频道发布新视频时,你会收到通知
- 你可以选择观看视频(响应通知)或者忽略它
再比如,天气应用:
- 天气服务是主题
- 你的手机应用是观察者
- 当天气变化时,应用会收到通知并更新显示
代码实现
让我们用TypeScript实现一个简单的观察者模式,模拟一个新闻发布系统:
// 定义观察者接口
interface Observer {
update(news: string): void;
}
// 定义主题接口
interface Subject {
registerObserver(observer: Observer): void;
removeObserver(observer: Observer): void;
notifyObservers(): void;
}
// 具体主题:新闻发布者
class NewsPublisher implements Subject {
private observers: Observer[] = [];
private latestNews: string = '';
registerObserver(observer: Observer): void {
if (!this.observers.includes(observer)) {
this.observers.push(observer);
}
}
removeObserver(observer: Observer): void {
const index = this.observers.indexOf(observer);
if (index !== -1) {
this.observers.splice(index, 1);
}
}
notifyObservers(): void {
this.observers.forEach(observer => observer.update(this.latestNews));
}
// 发布新闻并通知所有观察者
publishNews(news: string): void {
this.latestNews = news;
this.notifyObservers();
}
}
// 具体观察者:新闻订阅者
class NewsSubscriber implements Observer {
private name: string;
constructor(name: string) {
this.name = name;
}
update(news: string): void {
console.log(`${this.name} 收到新闻: ${news}`);
}
}
// 使用示例
const publisher = new NewsPublisher();
const subscriber1 = new NewsSubscriber('张三');
const subscriber2 = new NewsSubscriber('李四');
const subscriber3 = new NewsSubscriber('王五');
publisher.registerObserver(subscriber1);
publisher.registerObserver(subscriber2);
publisher.registerObserver(subscriber3);
publisher.publishNews('今天天气晴朗!');
// 输出:
// 张三 收到新闻: 今天天气晴朗!
// 李四 收到新闻: 今天天气晴朗!
// 王五 收到新闻: 今天天气晴朗!
publisher.removeObserver(subscriber2);
publisher.publishNews('李四已取消订阅,不会收到这条新闻');
// 输出:
// 张三 收到新闻: 李四已取消订阅,不会收到这条新闻
// 王五 收到新闻: 李四已取消订阅,不会收到这条新闻React中的观察者模式
在React中,观察者模式的应用非常广泛:
状态管理:Redux、MobX等状态管理库都使用了观察者模式
- Store(主题)维护状态
- 组件(观察者)订阅状态变化
- 当状态更新时,相关组件自动重新渲染
事件系统:React的事件系统也是观察者模式的应用
- DOM元素是主题
- 事件处理函数是观察者
- 当事件发生时,相应的处理函数被调用
观察者模式的优缺点
优点
- 松耦合:主题和观察者之间是松耦合的,它们可以独立变化
- 可扩展性:可以方便地添加新的观察者,而不需要修改主题的代码
- 符合开闭原则:对扩展开放,对修改关闭
缺点
- 通知顺序不可控:观察者被通知的顺序是随机的
- 可能引起循环依赖:如果观察者和主题相互观察,可能导致循环通知
- 内存泄漏风险:如果忘记取消订阅,可能导致内存泄漏
实际应用场景
- 用户界面更新:当数据变化时,自动更新UI
- 事件处理系统:如浏览器的事件系统
- 消息队列:如发布-订阅消息系统
- 状态管理:如Redux、MobX等状态管理库
- 日志系统:多个日志记录器观察系统事件
总结
观察者模式是一种强大的设计模式,它通过定义对象之间的一对多依赖关系,实现了对象之间的松耦合通信。在现代软件开发中,特别是在事件驱动编程和响应式编程中,观察者模式的应用非常广泛。
通过理解观察者模式,我们可以设计出更加灵活、可扩展的系统,使代码更易于维护和测试。