一、装饰者模式定义
装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象。这种为对象动态添加职责的方式就称为装饰者模式。装饰者对象和它所装饰的对象拥有一致的接口,对于用户来说是透明的。
和java等语言不同的是,java的装饰器模式是给对象动态添加职责,javascript中,给对象添加职责的能力是与生俱来的,更侧重于给函数动态添加职责。
二、java中的装饰者模式实现
package com.bobo.shejimoshi.derector; public class Plane {
public void fire(){
System.out.println("发射普通子弹");
}
}
package com.bobo.shejimoshi.derector; public class MissileDecorator {
private Plane plane;
public MissileDecorator(Plane plane){
this.plane=plane; } public void fire(){
plane.fire();
System.out.println("发射导弹");
}
}
可见在java等传统语言中,给对象动态增加职责的方式,并没有真正地改动对象自身,而是将对象放入另一个对象之中,这些对象都具有相同的对外接口。
三、javascript中的装饰者模式实现
3.1为javascript对象添加职责
在javascript中,给对象添加职责是与生俱来的本领。同样是上面的例子,在javascript中可以这么实现:
//装饰者模式
var plane={
fire:function(){
console.log("发射普通子弹");
},
}; var missileDecorator=function(){
console.log("发射导弹");
}; var fire1=plane.fire;
plane.fire=function(){
fire1();
missileDecorator();
}; plane.fire();
3.2为javascript函数添加职责
为函数添加一些功能,在java等语言中貌似只能直接改写该函数,这显然违反了开放—封闭原则;
如果不想更改原函数,可以像上面的例子,通过保存原函数引用的方式来改写某个函数,这种方式一种是需要借助中间变量保存原函数的引用,此外还会遇到this劫持的问题。
因此,比较好的方式是利用AOP来进行函数装饰。
Function.prototype.before
Function.prototype.before=function(beforeFn){
var _self=this;//保存原函数的引用
return function(){
beforeFn.apply(this,arguments);
return _self.apply(this,arguments);
};
}; document.getElementById=document.getElementById.before(function(){
alert();
}); var sel=document.getElementById('colorSelect');
如果想根据上一个函数的执行结果决定函数是否执行,甚至还可以这样写Function.prototype.before
Function.prototype.before=function(beforeFn){
var _self=this;
return function(){
if(beforeFn.apply(this,arguments)!==false){
_self.apply(this,arguments);
} };
};
使用这种方法还可以动态改变函数的参数:
var func=function(param){
console.log(param);
};
func=func.before(function(param){
param.b='b';
});
func({'a':'a'});//输出 'a':a,'b':b
Function.prototype.after
Function.prototype.after=function(afterFn){
var _self=this;
return function(){
var ret=_self.apply(this,arguments);
afterFn.apply(this,arguments);
return ret;
};
};