js中观察者模式的应用

    实际的移动端引用backbone框架过于庞大,最近代码重构,为了实现MVC的基本功能而写了一个小型的框架,其中比较核心的内容,大概就是事件的注册触发机制,大致的实现就应用到了设计模式中观察者模式。

技术分享

                  ObserverPattern模型 


    上图大概是观察者模式的基本构成,目标Subject,维护基本属性observers,可以添加和删除观察者,观察者Observer,里面有方法update,而目标Subject的notify方法则需要遍历自身observers属性每个成员,并执行它的update方法。


    而事件Event正是基于上述模型实现,Event本身维护一张注册表_ptnMap,用于注册方法(on方法)和触发(trigger方法),比方说事件的子类Model的某个实例,注册了change: attr1

   name     注册的内容ObserverPattern的实例
change: attr1

observers:[

 observer1{

    update:注册方法cb1

  },observer2{

    update:注册方法cb2

  },

.....],


    显然,trigger的方法只要执行Subject.notify()即可,

    Model在这个基础上,要维护attr1的值,变化了就trigger。


具体实现如下:

var ObserverPattern = function () {

  this.Observer = function () {

    this.update = function () {

    }

  };

  var Subject = this.Subject = function () {

    this.observers = [];

  };

  Subject.prototype.notify = function () {

    var count = this.observers.count();

     for (var i = 0; i < count; i++) {

        this.observers.getAt(i).update.apply(null, arguments);

     }

   };

   Subject.prototype.addObserver = function (observer) {

    if (!observer.update) {

       throw "no update interface in observer!"

     }

     this.observers.add(observer);

   };

   Subject.prototype.removeObserver = function (observer) {

     if (!observer.update) {

        throw "no update interface in observer!"

     }

     this.observers.remove(observer);

   };

};

var Event = function () {

};

Event.prototype.on = function (name, callback, context) {

   this._ptnMap || (this._ptnMap = {});

   var ptn = this._ptnMap[name];

   if (!ptn) {

    ptn = new ObserverPattern();

    ptn.subject = new ptn.Subject();

    this._ptnMap[name] = ptn;

   }

   var observer = new ptn.Observer();

   observer.update = function () {

    callback.apply(context || window, arguments);

   };

   observer.callback = callback;

   ptn.subject.addObserver(observer);

};

Event.prototype.trigger = function (name) {

   this._ptnMap || (this._ptnMap = {});

   var ptn = this._ptnMap[name];

   if (!ptn) {

    return;

   }

   var args = [];

   for(var i = 1, len = arguments.length; i < len; i++) {

    args.push(arguments[i]);

   }

   ptn.subject.notify.apply(ptn.subject, args);

};


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。