手写观察者模式:原理、实现与应用
🤍 前端开发工程师、技术日更博主、已过CET6
🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1
🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》
🍚 蓝桥云课签约作者、上架课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入门到实战全面掌握 uni-app》
文章目录
- 引言
- 观察者模式的基本原理
- 手写观察者模式的实现步骤
- 1. 定义观察者接口
- 2. 定义主题接口
- 3. 实现具体的主题类
- 4. 实现具体的观察者类
- 使用示例
- 观察者模式与发布 - 订阅模式的区别
- 应用场景
- 总结
引言
在软件开发领域,设计模式是解决常见问题的有效手段。观察者模式(Observer Pattern)作为一种行为设计模式,在实现对象之间的一对多依赖关系时发挥着重要作用。当一个对象的状态发生变化时,所有依赖它的对象都会得到通知并自动更新。这种模式使得对象之间的耦合度降低,提高了系统的可维护性和扩展性。本文将详细介绍观察者模式的原理、手写实现过程以及实际应用场景。
观察者模式的基本原理
观察者模式包含两个主要角色:
- 主题(Subject):也称为被观察对象,它维护一个观察者列表,当自身状态发生变化时,会通知列表中的所有观察者。
- 观察者(Observer):依赖于主题的对象,它向主题注册自己,以便在主题状态变化时接收通知,并执行相应的更新操作。
手写观察者模式的实现步骤
1. 定义观察者接口
首先,我们需要定义一个观察者接口,该接口包含一个更新方法,用于在主题状态变化时被调用。
// 定义观察者接口
class Observer {update() {throw new Error('This method must be overridden!');}
}
在上述代码中,Observer
类定义了一个 update
方法,由于这是一个抽象方法,所以在具体的观察者类中需要重写该方法。
2. 定义主题接口
接着,定义主题接口,该接口包含注册观察者、移除观察者和通知观察者的方法。
// 定义主题接口
class Subject {constructor() {this.observers = [];}registerObserver(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());}
}
在 Subject
类中,构造函数初始化了一个空的观察者列表 observers
。registerObserver
方法用于将观察者添加到列表中,removeObserver
方法用于从列表中移除指定的观察者,notifyObservers
方法遍历观察者列表,调用每个观察者的 update
方法。
3. 实现具体的主题类
现在,我们来实现一个具体的主题类,该类继承自 Subject
类,并包含一个状态属性。
// 具体的主题类
class ConcreteSubject extends Subject {constructor() {super();this.state = null;}getState() {return this.state;}setState(newState) {this.state = newState;this.notifyObservers();}
}
ConcreteSubject
类继承了 Subject
类的功能,并添加了一个 state
属性。getState
方法用于获取当前状态,setState
方法用于设置新的状态,并在状态更新后调用 notifyObservers
方法通知所有观察者。
4. 实现具体的观察者类
最后,实现具体的观察者类,该类继承自 Observer
类,并在 update
方法中实现具体的更新逻辑。
// 具体的观察者类
class ConcreteObserver extends Observer {constructor(subject) {super();this.subject = subject;this.subject.registerObserver(this);}update() {console.log(`Received update: New state is ${this.subject.getState()}`);}
}
ConcreteObserver
类在构造函数中接收一个主题对象,并将自己注册到该主题中。update
方法在接收到主题的通知后,打印出主题的新状态。
使用示例
// 创建主题对象
const subject = new ConcreteSubject();// 创建观察者对象
const observer1 = new ConcreteObserver(subject);
const observer2 = new ConcreteObserver(subject);// 改变主题状态
subject.setState('New State 1');// 移除一个观察者
subject.removeObserver(observer2);// 再次改变主题状态
subject.setState('New State 2');
在上述示例中,我们首先创建了一个主题对象 subject
和两个观察者对象 observer1
和 observer2
,并将它们注册到主题中。然后,改变主题的状态,两个观察者都会收到通知并打印出更新信息。接着,移除了 observer2
观察者,再次改变主题状态时,只有 observer1
会收到通知。
观察者模式与发布 - 订阅模式的区别
虽然观察者模式和发布 - 订阅模式在概念上有些相似,但它们也存在一些区别。观察者模式中,主题和观察者之间是直接耦合的,观察者需要向主题注册自己。而发布 - 订阅模式引入了一个中间的消息代理(事件中心),发布者和订阅者之间通过消息代理进行通信,耦合度更低。
应用场景
观察者模式在很多场景中都有广泛应用,例如:
- 图形用户界面(GUI):当一个组件的状态发生变化时,通知其他相关组件进行更新,如按钮点击后更新文本框的内容。
- 状态管理库:在前端开发中,像 Redux 和 Vuex 等状态管理库就运用了观察者模式,当状态发生变化时,通知所有订阅该状态的组件进行重新渲染。
总结
通过手写实现观察者模式,我们深入理解了其核心原理和实现细节。观察者模式通过建立对象之间的一对多依赖关系,实现了状态变化的自动通知和更新,降低了对象之间的耦合度。在实际开发中,合理运用观察者模式可以提高系统的可维护性和扩展性,使得代码更加灵活和易于管理。