JS设想形式之Obeserver(观察者)形式、Publish/Subscribe(宣布/定阅)形式

Obeserver(观察者)形式

定义

《js设想形式》中对Observer的定义:
一个对象(称为subject)保持一系列依赖于它(观察者)的对象,将有关状况的任何变动自动关照给它们。

《设想形式:可服用面向对象软件的基本》中对Observer的定义:
一个或多个观察者对目的的状况感兴趣,它们经由过程将本身依附在目的对象上以便注册所感兴趣的内容。目的状况发作转变而且观察者可能对这些转变感兴趣,就会发送一个关照音讯,挪用每一个观察者的更新要领。当观察者不再对目的感兴趣时,他们能够简朴地将本身从中星散。

下面看一个观察者形式的例子:

//观察者列表
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;
  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.addObserver = function(observer) {
  this.observers.add(observer);
};
Subject.prototype.removeObserver = 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(name, subject) {
  this.name = name;
  this.subject = subject;
  this.subscribe(this.subject);
}
Observer.prototype.update = function(context) {
  console.log('observer:' + this.name + ' content:' + context);
}
Observer.prototype.subscribe = function(subject) {
  this.subject.addObserver(this);
}


var subject1 = new Subject();
var subject2 = new Subject();
var observer1 = new Observer('observer1', subject1);
var observer2 = new Observer('observer2', subject1);
var observer3 = new Observer('observer3', subject2);
subject1.notify('999伤风灵');
subject2.notify('999胃泰');
//observer:observer1 content:999伤风灵
//observer:observer2 content:999伤风灵
//observer:observer3 content:999胃泰

经常使用的场景

  • 网页的事宜绑定

Publish/Subscribe(宣布/定阅)形式

下面我们来看一个宣布定阅的详细完成;

var pubsub={};
        (function(q){
            var topics={},
                subUid=-1,
                subscribers,
                len;
            //宣布播送事宜,包括特定的topic称号和参数
            q.publish=function(topic, args){
                if(!topics[topic]){
                    return false;
                }

                subscribers=topics[topic];
                len=subscribers ? subscribers.length : 0;

                while(len--){
                    subscribers[len].func(topic, args);
                }
                return this;
            };
            q.subscribe=function(topic, func){
                if(!topics[topic]){
                    topics[topic]=[];
                }

                var token=(++subUid).toString();
                topics[topic].push({
                    token:token,
                    func:func
                });
                return token;
            };

            q.unsubscribe=function(token){
                for(var m in topics){
                    if(topics[m]){
                        for(var i = 0, j=topics[m].length; i < j; i++){
                            if(topics[m][i].token === token){
                                topics[m].splice(i, 1);
                                return token;
                            }
                        }
                    }
                }
                return this;
            };
        })(pubsub);


        function log1(topic ,data){
            console.log(topic , data);
        }
        function log2(topic ,data){
            console.log("Topic is "+topic+" Data is "+data);
        }

        pubsub.subscribe("sss",log2);
        pubsub.subscribe("sss",log1);
        pubsub.subscribe("cccc",log2);
        pubsub.subscribe('aaa', log1);
        pubsub.publish("sss","aaaaa1");
        pubsub.publish("cccc","ssssss");
        pubsub.publish('aaa', 'hahahahah');
        //sss aaaaa1
        //Topic is sss Data is aaaaa1
        //Topic is cccc Data is ssssss
        //aaa hahahahah

区分

Observer形式请求愿望接收到主题关照的观察者或对象必需定阅内容转变的事宜。如图:
《JS设想形式之Obeserver(观察者)形式、Publish/Subscribe(宣布/定阅)形式》
Publish/Subscribe形式比较观察者形式则多了一个类似于话题调理中间的流程,宣布者和定阅者解耦。

观察者形式更像是去咖啡店点咖啡,向店家点一杯咖啡,然后做好后店家会送过来,我和店家是直接有交互的。

宣布定阅形式就像是我们微信内里定阅民众号,宣布者把文章宣布到这个民众号,我们定阅民众号后就会收到宣布者宣布的文章,我们能够关注和作废关注这个民众号。

现实运用

  • promise
  • jquery的Callback内部要领

感兴趣的小伙伴能够移步本身着手完成一个Promise

JS设想形式系列文章

JS设想形式之Obeserver(观察者)形式、Publish/Subscribe(宣布/定阅)形式
JS设想形式之Factory(工场)形式
JS设想形式之Singleton(单例)形式
JS设想形式之Facade(表面)形式
JS设想形式之Module(模块)形式、Revealing Module(展现模块)形式
JS设想形式之Mixin(混入)形式

    原文作者:大海怪
    原文地址: https://segmentfault.com/a/1190000018484540
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞