JavaScript设计模式之观察者模式

Apr 12, 2015

776

观察者模式是一种设计模式,其中一个对象(Subject)维持一系列依赖于它(Observer)的对象,将有关状态的任何变更自动通知给它们。当一个目标需要告诉观察者发生了什么事情,它会向观察者广播一个通知。以下我们采用JavaScript来实现观察者模式。

  • Subject(目标):维护一系列的观察者,方便添加或删除观察者。
  • Observer(观察者):为那些在目标状态发生改变时需获得通知的对象提供一个更新接口。

首先,实现一个ObserList,用于存储一系列的Observer,代码如下:

function ObserverList() {
  this.observerList = [];
}

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

ObserverList.prototype.Empty = function() {
  this.observerList = [];
};

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, pointer = -1;

  while (i < this.observerList.length) {
    if (this.observerList[i] === obj) {
      pointer = i;
      break;
    }
    i++;
  }

  return pointer;
};

ObserverList.prototype.RemoveIndexAt = function(index) {
  if (index > -1 && index < this.observerList.length) {
    this.observerList.splice(index, 1);
  }
};

接着,实现Observer,代码如下:

function Observer() {
  this.id = Math.floor(Math.random() * 100);
}

Observer.prototype.Update = function(value) {
  console.log(value + this.id);
};

最后,实现Subject,代码如下:

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

Subject.prototype.AddObserver = function(observer) {
  this.observers.Add(observer);
};

Subject.prototype.RemoveObserver = function(observer) {
  this.observers.RemoveIndexAt(this.observers.IndexOf(observer, 0));
};

Subject.prototype.Notify = function(content) {
  var observerCount = this.observers.Count();
  for (var i = 0; i < observerCount; i++) {
    this.observers.Get(i).Update(content);
  }
};

现在,观察者模式创建完毕,来写一下测试代码,如下:

var $subject = new Subject(),
  $observer1 = new Observer(),
  $observer2 = new Observer();

$subject.AddObserver($observer1);
$subject.AddObserver($observer2);
$subject.Notify("Hello: Observer ");
/*
输出如下:
Hello: Observer 19
Hello: Observer 16
*/

观察者模式,与发布订阅模式有些类似,但两者存在一些区别

  1. 观察者模式要求希望接收到主题通知的观察者必须订阅内容改变的事件;
  2. 发布订阅模式使用了一个主题/事件通道,这个通道介于订阅者和发布者之间,其目的是避免订阅者和发布者产生依赖。

以下是发布订阅模式的简单实现:

var pubsub = {};

(function(pubsub) {
  var topics = {},
    subUid = -1;

  //发布事件
  pubsub.publish = function(topic, args) {
    if (!topics[topic]) {
      return false;
    }

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

    while (len--) {
      subscribers[len].func(args);
    }

    return this;
  };

  //订阅事件
  pubsub.subscribe = function(topic, func) {
    if (!topics[topic]) {
      topics[topic] = [];
    }

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

  //取消订阅
  pubsub.unsubscribe = function(token) {
    for (var topic in topics) {
      if (topics[topic]) {
        for (var i = 0, j = topics[topic].length; i < j; i++) {
          if (topics[topic][i].token === token) {
            topics[topic].splice(i, 1);
            return token;
          }
        }
      }
    }
    return this;
  };
}(pubsub));

在平常工作中,经常使用Ajax来获取数据,然后在回调函数中操作DOM,可以采用发布订阅模式来解耦程序,使程序更简洁明了。

设计模式 」相关文章

Wen's Blog

文章归档 » 文章标签 » 博主:吴文伟,Web开发爱好者,专注于前端开发,该博客用于记录和分享平时遇到的一些问题以及知识。

订阅

联系方式

链接