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

观察者模式: 观察者(Observer)直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(Fire Event)观察者里的事件。

发布订阅模式: 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。

image.png

使用观察者模式,面向接口编程,实现松耦合。

发布订阅模式里,发布者和订阅者,不是松耦合,而是完全解耦的

  • 从表面上看:

观察者模式里,只有两个角色 —— 观察者 + 被观察者
而发布订阅模式里,却不仅仅只有发布者和订阅者两个角色,还有一个经常被我们忽略的 —— 经纪人Broker

  • 往更深层次讲:

观察者和被观察者,是松耦合的关系
发布者和订阅者,则完全不存在耦合

  • 从使用层面上讲:

观察者模式,多用于单个应用内部
发布订阅模式,则更多的是一种跨应用的模式(cross-application pattern),比如我们常用的消息中间件

// 观察者模式
// 观察者列表
function ObserverList () {
    this.observerList = [];
}

ObserverList.prototype.add = function (obj) {
    return this.observerList.push(obj);
}

ObserverList.prototype.count = function () {
    return this.observerList.length;
}

ObserverList.prototype.get = function (index) {
    if (index > -1 && index < this.observerList.length) {
        return this.observerList[index];
    }
}
ObserverList.prototype.indexOf = function (obj, startIndex) {
    var i = startIndex || 0;
    while (i < this.observerList.length) {
        if (this.observerList[i] === obj) {
            return i;
        }
        i++;
    }
    return -1;
}

ObserverList.prototype.removeAt = function (index) {
    this.observerList.splice(index, 1);
}

// 目标
function Subject () {
    this.observers = new ObserverList();
}

Subject.prototype.addObsever = function (observer) {
    this.observers.add(observer);
}

Subject.prototype.removeObsever = function (observer) {
    this.observers.removeAt(this.observers.indexOf(observer, 0));
}

Subject.prototype.notify = function (context) {
    var observerCount = this.observers.count();
    for(var i = 0; i < observerCount; i++) {
        this.observers.get(i).update(context);
    }
}

// 观察者
function Observer () {
    this.update = function (context) {
        console.log(context);
    }
}

var mySubject = new Subject();
mySubject.addObsever(new Observer);
mySubject.notify("hello world");


 // 发布订阅模式
        var Event = (function() {
            var obj = {},
                listen,
                trigger,
                remove;
            // 订阅 
            listen = function(key, fn) {
                    if (!obj[key]) {
                        obj[key] = []
                    }
                    obj[key].push(fn)
                }
                // 发布 触发
            trigger = function() {
                    // 获取key
                    var key = Array.prototype.shift.call(arguments)
                        // 如果没有订阅过 直接返回
                    var fnList = obj[key]
                    if (!fnList || fnList.listen === 0) {
                        return
                    }
                    // 遍历 订阅过的函数列表 分别触发
                    for (var i in fnList) {
                        // 执行函数 并把去掉key之后的参数传入
                        fnList[i].apply(this, arguments)
                            // fnList[i](...arguments)
                    }
                }
                // 移除监听如果没有传入 fn .把key所有的监听移除
            remove = function(key, fn) {
                var fnList = obj[key]
                if (!fnList) {
                    return
                }
                if (!fn) {
                    fnList.length = 0
                } else {
                    for (var i in fnList) {
                        if (fnList[i] == fn) {
                            fns.splice(i, 1)
                        }
                    }
                }
            }
            return {
                listen,
                trigger,
                remove
            }
        })()

        Event.listen('test', function(a, b) {
            console.log('监听test', a, b);
        })

        setTimeout(() => {
            Event.trigger('test', 111, 222)
        }, 2000)

你可能感兴趣的:(发布订阅模式与观察者模式)