2、观察者模式
2.1、观察者模式
2.1.1、前言
定义一种一对多的依赖关系,当一个对象发生变化时,所有依赖于它的对象都会自动收到通知并更新。
两个角色:
- Subject(主题/被观察者)
- Observer(观察者)
观察者模式一般至少有一个 Subject(主题) ,可以有多个Observer(观察者)。
二者关系: Subject(主题)主动建立与观察者的关系。
Subject(主题/被观察者):至少要有三个方法------添加观察者、移除观察者、通知观察者。
2.1.2、代码
javascript
<input type="text" id="app" oninput="handleInput(event)">
<script>
// 主题,接收状态变化,并通知每个观察者
class Subject {
constructor() {
this.observers = []
}
// 新增观察者
addObserver(observer) {
this.observers.push(observer)
}
// 通知每个观察者
notify(state) {
this.observers.forEach(observer => {
observer.update(state)
})
}
removeObserver(observer) {
const index = this.observers.indexOf(observer);
if (index !== -1) {
this.observers.splice(index, 1);
}
}
}
// 观察者,等待被通知
class Observe {
constructor(name) {
this.name = name
}
update(state) {
console.log(`${this.name} 获取到最新值:${state}`);
}
}
const handleInput = (e) => {
const event = e || event
const value = event.target.value
// 实例化一个主题
const sub = new Subject()
// 实例化两个观察者 一个沐歌,一个沐夏
const muge = new Observe('沐歌')
const muxi = new Observe('沐夏')
// 添加观察者实例
sub.addObserver(muge)
sub.addObserver(muxia)
// 状态改变,通知所有观察者
sub.notify(value)
}
</script>
2.2、发布订阅模式
2.2.1、前言
发布订阅模式在观察者模式的基础上加入了 事件调度中心,提供更灵活的控制,适用于复杂的消息交互场景。
观察者模式是经典的设计模式,观察者和目标之间直接交互,适合简单的一对多通知。
2.2.1、代码
/*
* @Author: muge
* @Date: 2021-05-21 18:46:09
* @LastEditors: Please set LastEditors
* @LastEditTime: 2023-03-09 16:37:47
*/
//仿vue-$on $emit
class Event {
// 首先定义一个事件对象,用来装事件数组(多个订阅者)
handlers = {};
// 订阅(事件添加方法) type=事件名 callback=回调函数
$on(type, callback) {
if (!this.handlers[type]) {
// 没有则初始化
this.handlers[type] = [];
}
// 存入该事件
this.handlers[type].push(callback);
}
// 触发事件 type=事件名 params=参数
$emit(type, params) {
// 若没有注册该事件则抛出错误
if (!this.handlers[type]) return new Error("未注册该事件");
// 事件触发
this.handlers[type].forEach((callback) => callback(params));
}
// 取消订阅 type=事件名 callback=回调函数
$unsubscribe(type, callback) {
// 无效事件抛出异常
if (!this.handlers[type]) return new Error("未注册该事件");
// 执行回调
callback&&callback()
// 删除事件
delete this.handlers[type];
}
}
// 创建一个event实例
const sub = new Event();
// 订阅事件changeInputValue onLaod
sub.$on("changeInputValue", (params) => {
console.log("params", params);
});
sub.$on("onLaod", (params) => {
console.log("params", params);
});
console.log('当前的事件列表',sub.handlers);
// 事件触发
sub.$emit("changeInputValue", "最新的值是:1");
sub.$unsubscribe('changeInputValue',()=>{
console.log('取消订阅,执行的回调');
})
console.log('changeInputValue-事件取消',sub.handlers);
DOM事件也是发布订阅模式。订阅window的onload事件,当window加载完毕时会向订阅者发布消息,执行相应的回调函数。
window.addEventListener('onload', function () {
console.log('loaded!')
})