js装饰者模式:
装饰者对象都将以构造函数的属性这种方式来实现
function Sale(price){
this.price = price || 100;
}
Sale.prototype.getPrice = function(){
return this.price;
};
Sale.decorators = {
fedtax : {
getPrice:function(){
var price = this.uber.getPrice();
price += price * 5 / 100;
return price;
}
},
quebec : {
getPrice : function(){
var price = this.uber.getPrice();
price += price * 7.5 / 100;
return price;
}
},
money : {
getPrice : function(){
return '$' + this.uber.getPrice().toFixed(2);
}
},
cdn : {
getPrice : function(){
return 'CDN$ ' + this.uber.getPrice().toFixed(2);
}
}
};
Sale.prototype.decorate = function(decorator){
var F = function(){},
overrides = this.constructor.decorators[decorator],
i,newobj;
console.log(this);
F.prototype = this; //除了第一次,每一次this的值都上一次的一个构造函数F的实例
newobj = new F();
newobj.uber = F.prototype;
for(i in overrides){
if(overrides.hasOwnProperty(i)){
newobj[i] = overrides[i];
}
}
return newobj;
};
var sale = new Sale(100);
sale = sale.decorate('fedtax');
sale = sale.decorate('quebec');
//sale = sale.decorate('money');
sale = sale.decorate('cdn');
sale.getPrice(); //先找到cdn的getPrice方法,依次再找this.uber.getPrice(),直到Sale.prototype.getPrice的方法,再从最内到往逐个运行
下面是最后newobj的原型结构
newobj: F
getPrice: function (){
arguments: null
caller: null
length: 0
name: ""
prototype: Sale.decorators.cdn.getPrice //cdn
__proto__: function Empty() {}
<function scope>
uber: F
__proto__: F
getPrice: function (){
arguments: null
caller: null
length: 0
name: ""
prototype: Sale.decorators.quebec.getPrice //quebec
constructor: function (){
__proto__: Object
__proto__: function Empty() {}
<function scope>
uber: F
__proto__: F
getPrice: function (){
arguments: null
caller: null
length: 0
name: ""
prototype: Sale.decorators.fedtax.getPrice //fedtax
__proto__: function Empty() {}
<function scope>
uber: Sale
__proto__: Sale
price: 100
__proto__: Sale //Sale.prototype.getPrice
constructor: function Sale(price){
decorate: function (decorator){
getPrice: function (){
__proto__: Object
还有一种使用列表来实现,这种方法更为简单,也不涉及继承,也更易于理解
var Sale = function (price){
this.price = (price > 0 ) || 100; //this.price为true的时候,在运算当中会作为1来处理,如果为false的时候,在参与参与去处的过程当中会作为0来处理
this.decorators_list = [];
};
Sale.prototype.decorate = function(decorator){
this.decorators_list.push(decorator);
};
Sale.prototype.getPrice = function(){
var price = this.price, i,
max = this.decorators_list.length,name;
for(i=0;i<max;i++){
name = this.decorators_list[i];
price = Sale.decorators[name].getPrice(price);
}
return price;
};
Sale.decorators = {
fedtax : {
getPrice : function(price){
return price + price * 5 / 100;
}
},
quebec : {
getPrice : function(price) {
return price + price * 7.5 / 100;
}
},
money :{
getPrice : function(price){
return '$' + price.toFixed(2);
}
}
};
var sale = new Sale(100);
sale.decorate('fedtax');
sale.decorate('quebec');
sale.decorate('money');
sale.getPrice();