观察者和主题之间存在直接的依赖关系,适合一对多的依赖关系,而发布者和订阅者之间解耦,彼此不需要直接知道对方的存在。,适合多对多的依赖关系。根据具体的场景和需求,选择合适的模式进行设计和实现。
- 发布订阅者
// 可以给同一个事件订阅多个回调函数,且支持订阅一次
class EventEmitter {
constructor() {
// 缓存列表
this.listener = {}
}
// 订阅
on(eventName, fn) {
// 如果对象中没有对应的 event 值,也就是说明没有订阅过,就给 event 创建个缓存列表
// 如有对象中有相应的 event 值,把 fn 添加到对应 event 的缓存列表里
if(!this.listener[eventName]){
this.listener[eventName] = [];
}
this.listener[eventName].push(fn);
}
// 取消订阅
off(eventName, fn) {
let callbacks = this.listener[eventName];
// 缓存列表中没有对应的fn,返回false
if(!callbacks){
return false;
}
if(!fn){
// 如果未传入fn,则将缓存列表中对应的fn都清空
callbacks && (callbacks.length = 0);
} else {
let cb;
// 遍历所对应的fn,判断和那个fn相同,相同则删除
for (let i = 0, cbLen = callbacks.length; i < cbLen; i++) {
cb = callbacks[i];
if (cb == fn || cb.fn == fn) {
callbacks.splice(i, 1);
break
}
}
}
}
// 监听一次
once(eventName, fn) {
// 先绑定,运行时删除对应的值
let on = () => {
this.off(eventName, on);
fn.apply(this, arguments);
}
on.fn = fn;
this.on(eventName, on);
}
// 发布
emit(eventName, data) {
const callbacks = this.listener[eventName];
if(callbacks) {
callbacks.forEach((c) => {
c(data);
})
}
}
}
let a = new EventEmitter();
function callback1(x) {
console.log('callback1', x);
}
function callback2(x) {
console.log('callback2', x);
}
// a.on("click", callback1)
// a.on("click", callback2)
a.once("onmonseover", callback1)
a.emit('onmonseover', 'onmonseover');
a.emit('onmonseover', 'onmonseover again');
// a.emit('click', 'click');
// a.off('click',callback1);
// a.emit('click', 'click again');
- 观察者模式
let observer_ids=0;
let observed_ids=0;
//观察者类
class Observer {
constructor() {
this.id = observer_ids++;
}
//观测到变化后的处理
update(ob){
console.log("观察者" + this.id + `-检测到被观察者${ob.id}变化`);
}
}
//被观察者列
class Observed {
constructor() {
this.observers = [];
this.id = observed_ids++;
}
//添加观察者
addObserver(observer) {
this.observers.push(observer);
}
//删除观察者
removeObserver(observer) {
this.observers = this.observers.filter(o => {
return o.id != observer.id;
});
}
//通知所有的观察者
notify() {
this.observers.forEach(observer => {
observer.update(this);
});
}
}
let mObserved = new Observed();
let mObserver1 = new Observer();
let mObserver2 = new Observer();
mObserved.addObserver(mObserver1);
mObserved.addObserver(mObserver2);
mObserved.notify();