美文网首页程序员让前端飞Web前端之路
JavaScript设计模型之观察者模式

JavaScript设计模型之观察者模式

作者: 慕时_木雨凡 | 来源:发表于2019-10-08 10:45 被阅读0次

    观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们能够自动更新。

    观察者模式主要分为三个阶段订阅on, 发布emit, 退订off

    观察者模式是依赖函数回调实现的

    观察者模式的好处

    1. 简单、灵活、可复用
    2. 可以让事件跟当前逻辑充分解耦,适合组件间的事件调用和数据传递
    3. 灵活性比较高

    如何理解观察者模式

    我想去篮球场打打球结果到篮球场时,篮球场管理员告诉我现在正在进行设备检修,什么时候能修好还不知道。
    如果我想进去这个篮球场打球怎么办?
    第一:每过一段时间过来看一下(轮询)
    第二:把我的手机号码留给篮球场管理员,球场修好之后给我打电话(观察者模式)

    结合上面的文字用代码实现

    1. 创建一个篮球场(Observe),并且在篮球场中创建一个对象eventObj(存储电话号码k和要做的事情)
    const Observe = function() {
        this.eventObj = {}; // 
    };
    
    1. 创建一个on方法,在eventObj中存储key(电话号码)以及对应的回调函数 -- 订阅
    Observe.prototype.on = function(ev, cb) {
        this.eventObj[ev] = cb;
    };
    
    1. 创建一个emit方法,当篮球场修好之后,找到我的电话并且执行回调函数 -- 发布
    Observe.prototype.emit = function(ev) {
      if (this.eventObj[ev]) {
        for (const key in this.eventObj) {
          if (key === ev) {
            let args = [];
            for(let i = 1; i<arguments.length; i++) {
              args[i - 1] = arguments[i]
            }
            this.eventObj[ev].apply(this, args)
          }
        }  
      }
    };
    
    1. 移除消息 -- 退订
    EventEmitter.prototype.off = function(ev, cb) {
      this.eventObj[ev] = null
    };
    
    1. 实际使用
    let Event = new Observe(); //
    
    Event.on('handleCall', (str)=>{
      console.log(str)
    })
    
    Event.emit('handleCell', '篮球场修好了,可以过来打篮球了')
    
    Event.off('handleCell') // 取消订阅
    

    完整代码

    const Observe = function() {
        this.eventObj = {};
    };
    
    Observe.prototype.on = function(ev, cb) {
        this.eventObj[ev] = [];
        this.eventObj[ev].push(cb);
        return this;
    };
    // 执行一次之后就销毁
    Observe.prototype.once = function(ev, cb) {
        let self = this;
        let fn = function() {
            self.off(ev, fn);
            let args = [];
            for(let i =0; i<arguments.length; i++) {
                args[i] = arguments[i]
            }
            cb.apply(self, args);
        };
        return this.on(ev, fn);
    };
    
    Observe.prototype.emit = function(ev) {
        for (const key in this.eventObj) {
            if (key === ev) {
                if (this.eventObj[ev]) {
                    const cbs = this.eventObj[ev] || [];
                    for (let i = 0 ; i < cbs.length; i++) {
                        let args = [];
                        for(let i = 1; i<arguments.length; i++) {
                            args[i - 1] = arguments[i]
                        }
                        cbs[i].apply(this, args);
                    }
                }
            }
        }
        return this;
    };
    // 注销观察者
    Observe.prototype.off = function(ev, cb) {
        if (arguments.length === 0) {
            this.eventObj = {};
            return this;
        }
    
        const cbs = this.eventObj[ev];
        if (!cbs) {
            return this;
        }
    
        if (arguments.length === 1) {
            this.eventObj[ev] = null;
        } else {
            cbs.map((item, i) => {
                if (item === cb) {
                    cbs.splice(i, 1);
                    return this;
                }
            });
        }
        return this;
    };
    export default Observe;
    

    相关文章

      网友评论

        本文标题:JavaScript设计模型之观察者模式

        本文链接:https://www.haomeiwen.com/subject/fvvsyctx.html