观察者模式和发布订阅者模式与EventBus

本文介绍了发布订阅者模式,其中一对多的依赖关系适用于EventEmitter类,而多对多关系通过观察者模式实现,如Observer和Observed类。作者通过实例展示了如何在不同场景下选择和使用这两种设计模式。
摘要由CSDN通过智能技术生成

观察者和主题之间存在直接的依赖关系,适合一对多的依赖关系,而发布者和订阅者之间解耦,彼此不需要直接知道对方的存在。,适合多对多的依赖关系。根据具体的场景和需求,选择合适的模式进行设计和实现。

  • 发布订阅者
// 可以给同一个事件订阅多个回调函数,且支持订阅一次
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();
  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值