var concreteSubject=new Subject();
//定义publishEvent方法,该方法的作用是通知所有的Observer,通知的内容是data
concreteSubject.publishEvent=function(data){
document.write(“published:”+data);
this.notify(data);
}
var concreteSubject=new Subject();
//定义publishEvent方法,该方法的作用是通知所有的Observer,通知的内容是data
concreteSubject.publishEvent=function(data) (
document.write(“published:”+data);
this.notify(data);
}
//新建一个Observer对象,并覆盖其Update方法
var concreteObserverl=new Observer();
concreteObserverl.Update=function(data){
document.write(“concreteObserverl received:”+data);
}
//将concreteObserverl订阅到concreteSubject
concreteSubject.addObserver(concreteObserverl);
//新建第二个Observer对象,并覆盖其Update方法
var concreteObserver2=new Observer();
concreteObserver2.Update=function(data){
document.write(“concreteObserver2 received:”+data);
}
//将concreteObserver2订阅到concreteSubject
concreteSubject.addObserver(concreteObserver2);
执行concreteSubject对象的publishEvent方法,发出通知。
此时程序将输出:
concreteObserverl received:msg
concreteObserver2 receired:msg
这样的输出结果说明concreteObserverl和concreteObserver2都接收到来自concreteSubject的通知。接下来调用removeObserver方法撤消一个concreteSubject的订阅。
再次发出通知:
这一次只有concreteObserver1对象接收到通知,程序输出结果为:
concreteObserver1 receired:msg
使用Observer模式可以在JavaScript中实现通用的事件机制。有些熟悉Ajax开发的朋友可能知道Prototype框架和Dojo框架这两个客户端框架。其实,这两个框架的事件机制就是采用了类似此处介绍的方法实现的,有兴趣的朋友可进一步研究。
6. Façade模式
(1)概念
Façade模式可以为子系统中的一组接口提供一个一致的界面,它定义了一个高层接口,这个接口使得相应的子系统更加容易使用。Façade模式在Web开发中的一个典型应用是实现统一的API接口,消除各种浏览器在具体特性实现中的差异。
(2)举例
在基于Ajax的Web开发中,当使用XHR对象请求服务器端的数据时,我们通常需要按照以下的步骤进行编程:
·创建XHR对象;
·注册回调函数;
·用open方法设置请求方式(POST/GET)、URL和模式(同步/异步);
·用send发送请求;
·监视请求的状态,当达到某一特定状态时,执行某项特殊功能。
可以看到,使用XHR对象的步骤是比较复杂的,在每个步骤中都需要考虑浏览器兼容性问题。
【补充】熟悉Prototype框架的朋友可能知道此框架提供了一个Ajax.Request对象,使用该对象不必劳开发人员考虑以上这些繁琐步骤以及步骤之后的细节,通过统一的方式即可调用。有兴趣的读者可以下载Prototype的源码自行学习Ajax.Request对象的具体实现方法,在此不再赘述。
下面,我们将通过一个简单的示例来说明Façade模式的应用。该示例的目标是向用户输出一行欢迎信息,提示用户使用的浏览器类型。为了简单起见,示例中仅区分IE和其他浏览器。相关的代码如下所示:
function IEBrowser() {
this.hello=function(){
alert(”IE browser”);
}
}
//非IE浏览器对象
function NonIEBrowser() (
this.hello =function(){
alert(“NonIE browser”);
}
}
//Facade对象
var Facade={};
Facade.hello=function(){
var browser;
//如果为IE浏览器
if(window.ActiveXObject) browser=new IEBrowser();
//如果为非IE浏览器
else browser=new NonIEBrowser();
Browser.hello();
);
Facade.hello方法根据浏览器类型,创建不同的browser对象,再调用browser对象的hello方法。这样对于用户而言,无需考虑浏览器的类型,只需要简单地调用Facade对象的hello方法即可。
另外,IEBrowser和NonIEBrowser分别是两个独立的类,它们的内部实现可能会在未来发生变化,但是这都不会影响到外部对象Facade对它们的调用,即Facade.hello的代码无需改变。