闲话少说,直接上代码
(一)Facade模式实例
var net=new Object();
net.READY_STATE_UNINITIALIZED=0;
net.READY_STATE_LOADING=1;
net.READY_STATE_LOADED=2;
net.READY_STATE_INTERACTIVE=3;
net.READY_STATE_COMPLETE=4;
net.ContentLoader=function(url,onload,onerror){
this.url=url;
this.req=null;
this.onload=onload;
this.onerror=(onerror) ? onerror : this.defaultError;
this.loadXMLDoc(url);
net.ContentLoader.prototype={
loadXMLDoc:function(url){
if (window.XMLHttpRequest){
this.req=new XMLHttpRequest();
} else if (window.ActiveXObject){
this.req=new ActiveXObject("Microsoft.XMLHTTP");
}
if (this.req){
try{
var loader=this;
this.req.onreadystatechange=function(){
loader.onReadyState.call(loader);
}
this.req.open('GET',url,true);
this.req.send(null);
}catch (err){
this.onerror.call(this);
}
}
},
onReadyState:function(){
var req=this.req;
var ready=req.readyState;
if (ready==net.READY_STATE_COMPLETE){
var httpStatus=req.status;
if (httpStatus==200 || httpStatus==0){
this.onload.call(this);
}else{
this.onerror.call(this);
}
}
},
defaultError:function(){
alert("error fetching data!"
+"\n\nreadyState:"+this.req.readyState
+"\nstatus: "+this.req.status
+"\nheaders: "+this.req.getAllResponseHeaders());
}
}
(二)Adapter模式实例
var xhr = new XMLHttpRequest();
xhr.open("GET", "myData.xml");
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
alert(xhr.responseXML);
}
}
xhr.send(null);
(三)Observer模式实例
window.onloadListeners=new Array();
window.addOnLoadListener(listener){
window.onloadListeners[window.onloadListeners.length]=listener;
}
window.onload=function(){
for(var i=0;i<window.onloadListeners.length;i++){
var func=window.onlloadListeners[i];
func.call();
}
}
(四)Singleton模式实例
var SingletonObj = {
property1: value1,
property2: value2,
...
method1:function(){
...
}
method2:function(){
...
}
...
}
function getSingletonObj() {
if(!top.SingletonObj) {
var top.SingletonObj = {
...
}
top.SingletonObj.init(...);
}
return top.SingletonObj;
}
(五)Command模式实例
function buttonOnclickHandler(event){
var data=calculate();
showData(dataTable,data);
}
function ajaxOnloadHandler(){
var data=calculate();
showData(otherDataTable,data);
}
function calculate(){
var data=new Array();
data[0]=6;
data[1]=data[0]/3;
data[2]=data[0]*data[1]+7;
return data;
}
function showData(table,data){
var newRow=createTableRow(table);
for (var i=0;i<data.length;i++){
createTableCell(newRow,data[i]);
}
}
buttonDiv.onclick=buttonOnclickHandler;
poller.onload=ajaxOnloadHandler;
(六)MVC应用实例
function Button(value,domEl){
this.domEl=domEl;
this.value=value;
this.domEl.buttonObj=this;
this.domEl.onclick=this.clickHandler;
}
Button.prototype.clickHandler=function(){
var buttonObj=this.buttonObj;
var value=(buttonObj && buttonObj.value) ?
buttonObj.value : "unknown value";
alert(value);
}
1.跨浏览器不一致性:Facade和Adapter模式
getLeft(e)来自Mike Foster的x库的一个函数简化版本。这个函数接受一个参数e,以一种全面的方式发现这个DOM元素的左边界的像素位置。
Facade的模式:
定义一个函数来隐藏代码,这使得其他代码更加容易阅读,并且将对象检测代码集中到了一个地方。如果发现在某种边界情况下对象检测代码不能正常工作,那么只需要在一个地方修改,就可以将影响扩散到所有调用它的代码中,这就是重构的一个基本原则,
Facade模式可以用来为一个服务或者一些功能的不同实现方式提供公共的访问点。
Adapter模式:
与Facade不同,我们为其中的一个子系统提供了一个额外的层,使得这个子系统展现出与另一个子系统相同的API。这个层称作适配器层(adapter)。
例:用Adapter模式,开发一个控件,使IE的ActiveX控件看起来像是与Mozilla内建的XMLHttpRequest对象一样。
2.管理事件处理函数:Observer模式
Observer模式: 一个操作应该是谁的职责?询问这个问题有些时候是很有帮助的。在这个组合函数的解决方案中,window对象负责获得到DOM元素的引用,随后window对象必须知道当前页面中包括哪些子系统。理想情况下,每个子系统应该自己负责获取它们需要的引用。按照这种方式,如果它包括在页面中,就会获得自己需要的引用;如果没有包括在页面中,就不必做这件事情。
//为了清晰地分离这个职责,可以允许这些系统通过传递一个函数来登记,从而在发生onload事件时得到通知,这些函数会在window.onload事件触发时调用。这里是一个简单的实现:
window.onloadListeners=new Array();
window.addOnLoadListener(listener){
window.onloadListeners[window.onloadListeners.length]=listener;
}
//窗口完全加载后,window对象只需要遍历这个数组,并且依次调用每个方法:
window.onload=function(){
for(var i=0;i<window.onloadListeners.length;i++){
var func=window.onlloadListeners[i];
func.call();
}
}
3 重用用户操作处理函数:Command模式
在面向对象语言的传统Command模式中,用户的交互都封装为Command对象,通常继承自一个基类或者实现一个接口。在这里我们使用一种略微不同的方法来解决相同的问题。因为在JavaScript中,函数本身就是头等对象,我们可以直接将它们当作Command对象来处理,与此同时仍然提供了相同的抽象级别。
将用户所做的事情都封装为Command对象可能看起来有点麻烦,但是这样做是有回报的。当所有的用户行为都封装在Command对象中时,我们就可以很容易地联合使用其他标准的功能。讨论最多的扩展是增加undo()方法,一旦完成了这个工作,就为在整个应用中提供通用的撤销(undo)功能奠定了良好的基础。
在一个更加复杂的例子中,Command在执行时可以被记录在一个栈中,用户可以通过撤销按钮来回退这个栈,从而将应用返回到以前的状态。
每个新的Command对象都放在栈的顶端,可以按顺序逐个回退。用户通过一系列写的操作创建了一个文档,然后选择整个文档时,一不小心点了删除按钮。当调用undo功能时,从栈中弹出最顶端的条目,然后调用它的undo()方法,恢复被删除的文本。后续的撤销操作可能是取消文本的选择,等等。
当然,使用Command模式来创建一个撤销栈,还要确保这些执行和撤销操作的组合能够返回系统的初始状态,对于开发者来说这意味着一些额外的工作。提供完善的撤销功能可以使得产品显得与众不同,特别是对于频繁或长时间使用的应用来说,这个功能更加重要。
4 保持对资源的唯一引用:Singleton模式
一个对象只有一个实例,有时也描述为一个单例(singleton)。
Java中的单例
Java的语言中,实现单例的方法通常是隐藏对象的构造函数,并且提供一个getter方法,基于Java的解决方案利用private和public的访问修饰符来强化单例的行为
JavaScript中的单例
们可以按照平常的方式来定义TradingMode对象:
function TradingMode(){
this.mode=MODE_RED;
}
TradingMode.prototype.setMode=function(){
}
然后提供一个全局变量作为一个伪单例:
TradingMode.instance=new TradingMode();
但是这无法阻止恶意代码调用构造函数。另一方面,我们可以不使用原型,手工创建整个对象:
var TradingMode = new Object();
TradingMode.mode = MODE_RED;
TradingMode.setMode = function() {
...
}
也可以用更加简洁的方式来定义它:
var TradingMode = {
mode:MODE_RED,
setMode:function(){
...
}
};