1、观察者模式
定义对象间的一种一对多的依赖关系,是的每当一个对象状态发送改变时,其相关依赖对象皆得到通知并被自动更新。
// 被观察者
class Subject {
// 初始化一个空数组,用于存储观察者对象
constructor(){
this.observerList = [];
}
// 添加观察者
addObserver(observer){
this.observerList.push(observer);
}
// 移除观察者
removeObserver(observer){
const index = this.observerList.findIndex(obj => obj.name === observer.name);
if(index !== -1){
this.observerList.splice(index,1);
}
}
// 通知
notify(message){
this.observerList.forEach(observer => observer.update(message));
}
}
// 观察者
class Observer{
constructor(name,subject){
this.name = name;
// 主动加入
if(subject){
subject.addObserver(this);
}
}
// 订阅信息
update(info){
console.log(this.name,"get message",info);
}
}
// 创建被观察者
let subject = new Subject("")
// 创建观察者
let observerA = new Observer("observerA",subject);
let observerB = new Observer("observerB");
// 添加观察者(手动加入)
subject.addObserver(observerB);
// 通知
subject.notify("Hello observer");
// 移除观察者
subject.removeObserver(observerA);
// 更新数据
subject.notify("Hello again");
2、发布-订阅者模式
发布者不需要直接知道订阅者的存在,订阅者也不需要直接知道发布者的存在。它们通过一个中介(通常是一个事件总线或事件管理器)进行通信。
// 发布-订阅模式
class PubSub {
constructor() {
// 存储发布信息(键是消息类型,值是包含该类型消息的数组)
this.messages = {};
// 存储订阅者(键是消息类型,值是包含订阅者函数的数组)
this.listeners = {};
}
// 发布消息
publish(type, content) {
const existContent = this.messages[type];
if (!existContent) {
this.messages[type] = [];
}
this.messages[type].push(content);
}
// 订阅消息
subscribe(type, cb) {
const existListener = this.listeners[type];
if (!existListener) {
this.listeners[type] = [];
}
this.listeners[type].push(cb);
}
// 通知订阅者
notify(type) {
const messages = this.messages[type];
const subscribers = this.listeners[type] || [];
// subscribes.forEach((cd,index) => cd(messages[index]));
messages.forEach((message) => subscribers.forEach((cb) => cb(message)));
}
}
// 发布者
class Publisher {
constructor(name, context) {
this.name = name;
this.context = context;
}
publish(type, content) {
this.context.publish(type, content);
}
}
// 订阅者
class Subscriber {
constructor(name, context) {
this.name = name;
this.context = context;
}
subscribe(type, cd) {
this.context.subscribe(type, cd);
}
}
// 创建一个 Pubsub 实例
const pubsub = new PubSub();
// 订阅消息
pubsub.subscribe('news', (message) => {
console.log(`Subscriber 1: ${message}`);
});
pubsub.subscribe('news', (message) => {
console.log(`Subscriber 2: ${message}`);
});
// 发布消息
pubsub.publish('news', 'New article published!');
// 通知订阅者
pubsub.notify('news');
3、区别
设计模式 | 观察者 | 发布订阅者 |
主体 | Object(观察者)、Subject(目标对象) | Publisher(发布者)、Event Channel(事件中心)、Subscribe(订阅者) |
主体关系 | Subject通过observerList记录Object | Publisher和Subscribe并不需要知道对方的存在,通过中介联系 |
优点 | 角色明确,通用性强 | 解耦性强,灵活性高 |
缺点 | 紧耦合 | 通用差 |
常用场景 | 双向数据绑定、组件间通信、全局状态管理等方面 | 事件总线EventBus、事件监听、状态监控等 |
4、耦合
“耦合”是指不同代码组件或模块之间的依赖程度。耦合的强弱直接影响到代码的可维护性、可重用性和可扩展性。
高耦合
高耦合的代码意味着组件之间紧密相连,一个组件的修改可能影响到其他多个组件,这使得代码难以理解和维护。
低耦合
低耦合的代码则更加模块化,组件之间相对独立,修改一个组件通常不会影响到其他组件。