dahong icon indicating copy to clipboard operation
dahong copied to clipboard

一看就懂的设计模式之发布/订阅模式

Open shaodahong opened this issue 7 years ago • 6 comments

发布(Publish)/订阅(Subscribe)模式

简称pub/sub,pub/sub模式是我们平时业务中经常会使用到的,sub会监听一类消息来达到pub发布的时候进行相应的逻辑处理

qq20170310-231820 2x

举个例子,比如页面上有个列表,当我们点击刷新的时候要更新列表,当我们添加一个数据的数据的要更新列表,当我们删除一个数据的时候要更新列表,这时候我们就可以用到pub/sub模式

好,我们来简单写个pub/sub模式

var scope = (function() {
    	//消息列表
        var events = {};
        return {
        	//消息订阅
            on: function(name, handler) {
                var index;	//记录当前消息事件的索引
                //如果该消息已经存在,则将处理函数放到该消息的事件队列中
                if (events[name]) {
                    index = events[name].push(handler) - 1;
                } else {
                	//如果该消息已经不存在,则创建该消息的事件队列,并将处理函数放到该消息的事件队列中
                    events[name] = [handler];
                    index = 0;
                }
                //返回当前消息处理事件的移除函数
                return function() {
                    events[name].splice(index, 1);
                }
            },
            //消息关闭
            off: function(name) {
                if (!events[name]) return;
                //如果该消息存在,则将该消息删除
                delete events[name];
            },
            //消息发布
            emit: function(name, msg) {
            	//如果该消息不存在,不处理
                if (!events[name]) {
                    return;
                }
                //该消息存在,将该消息事件队列中的事件都处理一遍
                events[name].forEach(function(v, i) {
                    v(msg);
                })
            }
        }
    })()

    var remove = scope.on('refreshFileList', function(msg) {
        //处理逻辑
    })

    //点击刷新
    var refresh = function () {
    	scope.emit('refreshFileList')
    }

    //添加数据
    var addItem = function () {
    	scope.emit('refreshFileList')
    }

    //删除数据
    var removeItem = function () {
    	scope.emit('refreshFileList')
    }

    var destroy = function () {
    	remove();	//移除refreshFileList中对应的事件
    	scope.off('refreshFileList');	//移除refreshFileList
    }

shaodahong avatar Mar 10 '17 14:03 shaodahong

@Redshao 写的确实很简单易懂,如果能结合一下vue中的mvvm那种数据劫持应该可以写出更优雅的使用方式~

obetame avatar Mar 13 '17 10:03 obetame

@zhouyuexie 恩,一些热门的框架底层都是对一些常用的增删查改、事件等进行了封装,并且应用了一些良好的设计模式进行解耦和包装,对于使用者来说很便利,但是原理还是值得每个程序员深入学习的

shaodahong avatar Mar 13 '17 12:03 shaodahong

@Redshao 是啊,天天都在用的东西却不懂原理是有点尴尬,有个建议你看看能否优化?

events[name] = [];
events[name].push(handler);
// 感觉上面两行可以简化成下面这一行代码
events[name] = [handler]

obetame avatar Mar 14 '17 01:03 obetame

@zhouyuexie 好的,已修改

shaodahong avatar Mar 14 '17 02:03 shaodahong

下边的删除数据、添加数据这是没写完吗

//添加数据
var addItem = function () {
	scope.emit('refreshFileList')
}

//删除数据
var removeItem = function () {
	scope.emit('refreshFileList')
}`

gaoxuerong avatar Jan 22 '19 08:01 gaoxuerong

@gaoxuerong

var remove = scope.on('refreshFileList', function(msg) {
  //处理逻辑
})

在上面

shaodahong avatar Jan 22 '19 08:01 shaodahong