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 获取某观察者对象的位置属性(从最后面开始算)
具体代码
非常不错!你现在可以创建观察者模式中的 观察者类 和 主题类 了。
观察者类
观察者类,你只需要定义Update方法:
主题类
好了,让我们定义三个主要的方法:Nofify、AddObserver和RemoveObserver:
JavaScript中的继承
在JavaScript中有许多方法来模拟继承。一个非常简单的方式是定义一个名称为 Inherits 的方法,在该方法中,你可以复制一个对象的所有属性和方法到另一个对象中。
一个简单的实现
现在你需要实现客户端功能以便能够附加“观察者”到相应的“主题”上。例如,你可以创建一个简单的应用程序,在应用程序中定义一个主 checkbox,作为被观察对象,然后,再定义另一些checkbox作为观察者。当 主题 对象自身的状态发生变化的时候,它将通知所有依附它的 观察者。在 主题 对象中各自独立的 观察者 将独自处理这个消息。
在特定情况下,所有的 观察者 对象都使用同样的方式来处理(主题对象的)消息。当对应的 主题 对象通知这些观察者有关它的“新状态”的时候,任何一个观察者都会改变自己的状态,并把这个可被观察的状态作为它的新的值。
来源:http://hi.baidu.com/zhoumm1008/blog/item/17a3911639fe361e5baf537c.html
观察者模式 定义了一个 主题对象 和若干 观察者对象之间的 “一对多”的依赖。因此,当 主题对象 改变了其状态,所有的 观察者对象 都会被通知并且自动更新。
参与者:
* 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;
}
{
//初始化空数组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;
}
}
{
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));
}
{
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
}
}
}
{
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);
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
加支付宝好友偷能量挖...