3.Factory Method模式
(1)概念
根据GoF的定义,Factory Method模式的目的是为了定义一个创建对象的接口,由子类来决定实例化哪一个类。更准确地说应该是,Factory
Method模式是将创建对象实例的责任转移到工厂类中,并利用抽象的原理,将实例化行为延迟到具体工厂类中。
(2)举例
在某些情况下,我们的确无法确定将要创建的对象是哪个类的实例,这样的一个典型示例就是在Ajax应用程序中需要创建XMLHttpRequest(XHR)对象时,因为大家都知道在不同的浏览器中XHR对象的实现类是不同的。
通过引入Factory Method模式,我们即可以轻松使用JavaScript实现创建通用的XHR对象,相应的代码实现如下所示。
function
XMLHttpFactory(){}
XMLHttpFactorv.CreateXMLHttp=function()
{
if(typeof
XMLHttpRequest!=”undefined”){
//支持XMLHttpRequest对象的浏览器:例如Firefox等
return
new
XMLHttpRequest();
}else
if(typeof
window.ActiveXObject!=”undefined”){
//支持ActiveX对象的浏览器,即IE
return
new
ActiveXObject(“MSXML2.XMLHttp”);
}
}
然后,通过以下代码便可以相当容易地判断出浏览器的类型并进而创建XHR对象。
var
xmlhttp=XMLHttpFactory.createXMLHttp();
此后,基于以上创建的XHR对象就可以进行Ajax风格的服务器端调用了。
4.Decorator模式
(1)概念
Decorator模式是结构型模式的一种,它充分利用了继承与聚合的优势,其主要目的是为了给一个对象动态地添加以新的职责,而此职责并不修改原有的行为,而是在原有行为基础上添加新的功能,就好比装饰工人为一座新居的墙上涂抹上色彩缤纷的颜料一般。
【备注】面向方面编程(AOP),是一种改进已经存在的模式和发现新模式的方法。面向方面的编程能够独立于任何继承层次结构而应用改变类或对象行为的方面。然后,在运行时或编译时应用这些方面。AOP编程引入了一组新概念:接合点(Joinpoint)—代码中定义明确的可识别的点。切点(Pointcut)—通过配置或编码指定接合点的一种方法。通知(Advice)—表示需要执行交叉切割动作的一种方法。混入(Mixin)—通过将一个类的实例混入目标类的实例引入新行为。对于好的编程来说,设计模式已经变成了常用的方式。AOP可以给我们实际上,横切关注点代码的注入,因此说它也就是一种新式类型的软件设计模式。
(2)举例
有意思的是,我们也可以把Decorator模式应用于JavaScript中实现面向方面编程(AOP)。现在,不妨让我们观察一下列表3中定义的代码。
列表3:使用Decorator模式在JavaScript中实现面向方面编程(AOP)
function
Decorator(object){
object.setup=function(method){
//如果从未执行过Setup方法,则进行初始化
if(!(‘_’+method
in
object)){
//保留原有的method方法
object[‘_’+method]=object[method];
//初始化前置和后置通知的列表
object[‘beforeAdvice_’+method]=[];
object[‘afterAdvice_’+method] =[];
//改写method方法
object[method]=function(){
//前置通知列表
var
before=this[‘beforeAdvice_’+method];
//后置通知列表
var
after=this[‘afterAdvice_’+method];
//返回值
var
ret;
//执行前置通知中的函数
for(var
i=0; i<before.length; i++) {
before[i].call(this,arguments);
}
//执行原有的方法
ret=this[‘_’ +method](arguments);
//调用后置通知中的函数
for
(var
i=; i<after.1ength; i++){
after[i].call(this,
arguments);
}
//返回原有方法的返回值
return
ret;
}
}
};
//添加前置通知
object.addBeforeAdvice=function(method,
f) {
object.setup(method);
//最后添加的前置通知将最先被执行
object[‘beforeAdvice_’
+method].unshift(f);
};
//添加后置通知
object.addAfterAdvice=function(method,
f) {
object.Setup(method);
//最后添加的后置通知将最后被执行
object[‘afterAdvice_’ +method].push(f);
};
}
Decorator函数的基本思路是将原有的函数替换,在替换后的函数中增加对前置、后置通知的调用。下面通过一个具体的示例来说明Decorator函数的使用方法,首先定义一个类testClass。
var
testClass = function() {
testClass.prototype.pl=”hello”;
testClass.prototype.ml =function() {
alert(this.p1);
}
};
如果希望在所有testClass类的实例上增加前置或后置通知,那么需要对testClass.prototype属性进行处理。
Decorator(testClass.prototype);
testClass.prototype.addBeforeAdvice(“m1”,
function() {
alert(“beforeAdvice”);
});
testClass.prototype.addAfterAdvice(“m1”,
function() {
alert(”afterAdvice”);
});
此时,创建一个testClass类的对象实例,并且执行它的ml方法,程序将依次输出“beforeAdvice”、“hello”和“afterAdvice”。
var
t=new
testClass ();
t.ml(); //依次输出“beforeAdvice”、“hello”和“afterAdvice”
如果仅希望对testClass类的某个具体实例添加前置、后置通知,那么直接处理该实例即可。
var
t=new
testClass();
Decorator(t);
t.addBeforeAdvice(“ml” ,function](){
alert(“beforeAdvice”);
});
t.addAfterAdvice(“ml”, function(){
alert(“afterAdvice”);
});