javascript观察者模式

观察者模式类图

  观察者模式 定义了一个 主题对象 和若干 观察者对象之间的 “一对多”的依赖。因此,当 主题对象 改变了其状态,所有的 观察者对象 都会被通知并且自动更新。

参与者
  * Subject(抽象主题)
  * 能够知道它自己的观察者,若干观察者对象可能监视一个主题对象;
  * 提供一个接口,用来附加和取消观察者对象;
  * Observer(抽象观察者)
  * 它为对象定义了一个(自我)更新的接口,并且当主题对象发生改变的时候能够被通知;
  * ConcreteSubject(具体主题)
  * 存储具体观察者感兴趣的状态;
  * 当它的状态改变的时候,通知它所有的观察者对象;
  * ConcreteObserver(具体观察者)
  * 持有一个具体主题的引用;
  * 存储和主题对象一致的状态,并且该能够保留该状态;
  * 实现抽象观察者的Update接口,以便能够同主题对象的状态保持一致;

工作方式:
  * 当某个具体主题状态发生改变的时候,通知它的所有观察者对象,以便保证这些观察者对象的状态同它的状态保持一致;
  * 当被告知具体主题对象发生改变,一个具体观察者对象可能会去查询主题对象,以便获得一个消息;该观察者使用这个消息来使它的状态同主题对象的状态保持一致;

观察者模式序列图

  下面这张交互图展示了一个主题对象和两个观察者对象之间的协作:

  观察者对象初始化变化请求,它不会立即更新,直到通过主题对象的Notify方法来获得一个变化的通知。主题的Notify方法并非总是被主题对象调用,它也能够被观察者对象调用,或者完全被其他不同类型的对象调用。

接下来我们将做什么
  现在你已经知道了什么是 观察者模式,并且也了解了如何使用JavaScript来创建自己的对象。正如你在图1中看到的一样,你必须在 主题类 中定义2个方法(Attach 和 Detach)。为了达到这个目的,你需要一个 集合 来完成 Attach/Detach 方法。现在是时候写你的第一个JavaScript ArrayList 对象了。在定义 ArrayList 对象之前,你必须知道 ArrayList 能够完成一些什么样的功能。
ArrayList功能列表
方法名称 说明
Count 计算观察者对象的个数
Add 为主题添加一个观察者
GetAt 获取指定位置的观察者
Clear 清空主题的观察者对象
RemoveAt 删除指定位置的观察者对象
Insert 在指定位置插入一个观察者对象
IndexOf 获取某观察者对象的位置属性
LastIndexOf 获取某观察者对象的位置属性(从最后面开始算)
具体代码

+展开
-JavaScript
function ArrayList()
{
    //初始化空数组this.aList = [];
}
ArrayList.prototype.Count = function()
{
    returnthis.aList.length;
}
ArrayList.prototype.Add = function(object)
{
    //把新添加的对象放在数组的最后returnthis.aList.push(object);
}
ArrayList.prototype.GetAt = function(index)  //index必须是整数
{
    if (index > -1 && index < this.aList.length)
    {
       returnthis.aList[index];
    }
    else
    {
       return undefined;  //超出了数组范围,返回undefined
    }
}
ArrayList.prototype.clear = function()
{
    this.aList = [];
}
ArrayList.prototype.RemoveAt = function(index)
{
    var m_count = this.aList.length;
    if (m_count > 0 && index > -1 && index < this.aList.length)
    {
       switch (index)
       {
           case 0:
              //移除数组中的第一个元素this.aList.shift();
              break;
           case m_count - 1:
              //移除数组中最后一个元素this.aList.pop();
              break;
           default:
              //获取前面index个元素,生成一个新数组var head = this.aList.slice(0, index);
              //获取index之后的元素,生成一个新数组var tail = this.aList.slice(index + 1);
              //组合两个子数组this.aList = head.concat(tail);
              break;
       }
    }
}
ArrayList.prototype.Insert = function(object, index)
{
    var m_count = this.aList.length;
    var m_returnValue = -1;
    if (index > -1 && index <= m_count)
    {
       switch (index)
       {
           case 0:
              this.aList.unshift(object);
              m_returnValue = 0;
              break;
           case m_count:
              this.aList.push(object);
              m_returnValue = m_count;
              break;
           default:
              var head = this.aList.slice(0, index - 1);
              var tail = this.aList.slice(index);
              this.aList = header.concat(tail.unshift(object));
              m_returnValue = index;
              break;
       }
    }
    return m_returnValue;
}
ArrayList.prototype.IndexOf = function(object, startIndex)
{
    var m_count = this.aList.length;
    var m_returnValue = -1;
    if (startIndex > -1 && startIndex < m_count)
    {
       var i = startIndex;
       while (i < m_count)
       {
           //循环遍历数组,直到找到和参数object相同的元素if (this.aList[i] == object)
           {
               m_returnValue = i;
               break;
           }
           i++;
       }
    }
    return m_returnValue;
}
ArrayList.prototype.LastIndexOf = function(object, startIndex)
{
    var m_count = this.aList.length;
    var m_returnValue = -1;
    if (startIndex > -1 && startIndex < m_count)
    {
       var i = m_count - 1;
       while (i >= startIndex)
       {
           if (this.aList[i] == object)
           {
              m_returnValue = i;
              break;
           }
           i--;
       }
    }
    return m_returnValue;
}


  非常不错!你现在可以创建观察者模式中的 观察者类 和 主题类 了。

观察者类

观察者类,你只需要定义Update方法:


+展开
-JavaScript
function Observer()
{
    this.Update = function()
    {
       return;
    }
}


主题类

  好了,让我们定义三个主要的方法:Nofify、AddObserver和RemoveObserver:


+展开
-JavaScript
function Subject()
{
    this.observers = new ArrayList();
}

Subject.prototype.Notify = function(context)
{
    var m_count = this.observers.Count;
    for (var i = 0; i < m_count; i++)
    {
       this.observers.GetAt(i).Update(context);
    }
}

Subject.prototype.AddObserver = function(observer)
{
    if (!observer.Update)
    {
       throw'Wrong parameter';
    }
    this.observers.Add(observer);
}

Subject.prototype.RemoveObserver = function(observer)
{
    if (!observer.Update)
    {
       throw'Wrong parameter';
    }
    this.observers.RemoveAt(this.observers.IndexOf(observer, 0));
}


JavaScript中的继承

  在JavaScript中有许多方法来模拟继承。一个非常简单的方式是定义一个名称为 Inherits 的方法,在该方法中,你可以复制一个对象的所有属性和方法到另一个对象中。


+展开
-JavaScript
function Inherits(base, extension)
{
    for (var property inbase)
    {
       try
       {
           extention[property] = base[property];
       }
       catch (e)
       {
           //Exception Handle
       }
    }
}


一个简单的实现

  现在你需要实现客户端功能以便能够附加“观察者”到相应的“主题”上。例如,你可以创建一个简单的应用程序,在应用程序中定义一个主 checkbox,作为被观察对象,然后,再定义另一些checkbox作为观察者。当 主题 对象自身的状态发生变化的时候,它将通知所有依附它的 观察者。在 主题 对象中各自独立的 观察者 将独自处理这个消息。


+展开
-JavaScript
/************* Concrete Subject *************/
var mainCheck = document.createElement("input");
mainCheck.type = 'checkbox';
mainCheck.id = 'MainCheck';

Inherits(new Subject(), mainCheck);
mainCheck["onclick"] = new Function("mainCheck.Notify(mainCheck.checked)");

/**************** Observer ****************/var obsCheck1 = document.createElement("input");
var obsCheck2 = document.createElement("input");

obsCheck1.type = 'checkbox';
obsCheck1.id = 'Obs1';

obsCheck2.type = 'checkbox';
obsCheck2.id = 'Obs2';

Inherits(new Observer(), obsCheck1);
Inherits(new Observer(), obsCheck2);

obsCheck1.Update = function(value)
{
    this.checked = value;
}

obsCheck2.Update = function(value)
{
    this.checked = value;
    //Add
}

mainCheck.AddObserver(obsCheck1);
mainCheck.AddObserver(obsCheck2);




  在特定情况下,所有的 观察者 对象都使用同样的方式来处理(主题对象的)消息。当对应的 主题 对象通知这些观察者有关它的“新状态”的时候,任何一个观察者都会改变自己的状态,并把这个可被观察的状态作为它的新的值。


来源:http://hi.baidu.com/zhoumm1008/blog/item/17a3911639fe361e5baf537c.html

加支付宝好友偷能量挖...


评论(0)网络
阅读(118)喜欢(1)JavaScript/Ajax开发技巧