Last active
December 14, 2015 02:19
-
-
Save kampfer/5012413 to your computer and use it in GitHub Desktop.
Decorator Pattern In JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 装饰器模式在javascript中的实现方式 | |
* | |
* 装饰器模式的优点: | |
* 1.动态的添加和删除职责 | |
* 2.避免子类爆炸 | |
* 3.避免在高层次结构的类中定义过多的特性 | |
* | |
* 使用多个装饰器组合生成一个多功能的对象时,创建代码会相当长, | |
* 可以使用工厂模式处理这个问题. | |
* | |
* 装饰器和被它装饰的类必须保持接口一致.在设计新系统时使用装饰器模式, | |
* 可以为装饰器和被装饰的类定义共同的父类来保证两者接口一致; | |
* 在重构已有系统时可以省略这个父类,直接定义一个和被装饰类接口一样的装饰器. | |
* 这个父类是不必需的. | |
* | |
* 当被装饰的对象的类太庞大时,就要慎重的使用装饰器.因为装饰器必须和被装饰得对象 | |
* 保持接口一致,为了装饰一个庞大的类我们也要实现一个庞大的装饰器,有点得不偿失. | |
*/ | |
function decorate(Component, decorator) { | |
var Class = function(comp) { | |
for(var prop in decorator) { | |
this[prop] = decorator[prop]; | |
} | |
this.__component__ = comp; | |
}; | |
//Class继承Compoent的所有方法 | |
var F = function() {}; | |
F.prototype = Component.prototype; | |
Class.prototype = new F(); | |
return Class; | |
} | |
function Sale(price) { | |
this.price = price || 100; | |
} | |
Sale.prototype.getPrice = function() { | |
return this.price; | |
}; | |
Sale.prototype.discount = function() { | |
return parseInt(this.getPrice(), 10) * 0.5; | |
}; | |
var FedtaxSale = decorate(Sale, { | |
getPrice : function() { | |
var price = this.__component__.getPrice(); | |
price += price * 5 / 100; | |
return price; | |
} | |
}); | |
var UsdSale = decorate(Sale, { | |
getPrice : function() { | |
return "$" + this.__component__.getPrice().toFixed(2); | |
} | |
}); | |
var sale = new Sale(5); | |
var fedtaxSale = new FedtaxSale(sale); | |
var usdFedtaxSale = new UsdSale(fedtaxSale); | |
console.log( sale.getPrice() ); | |
//console.log( sale.discount() ); | |
console.log( fedtaxSale.getPrice() ); | |
//console.log( fedtaxSale.discount() ); | |
console.log( usdFedtaxSale.getPrice() ); | |
//console.log( usdFedtaxSale.discount() ); |
- 不应该改变被装饰得对象
- 装饰器和被装饰对象的接口一致
区别于继承:
- 继承是静态的, 运行时无法改变, 装饰器可以.
- 为一个基类添加大量的功能, 会造成子类爆炸.比如:
我们有一个基类Hero, 当Hero拥有大量特性的时候, 如:runQuickly、seeFar、canfly等。那么我们生成所有可能的特性组合就有:HeroRunQuickly、HeroSeeFar、HeroCanFly、HeroRunQuicklyAndSeeFar、HeroRunQuicklyAndCanFly、HeroSeeFarAndCanFly、HearRunQuicklyAndSeeFarAndCanFly之多,使用装饰器我们只用写3个。如果我们还要加特性,那么子类就爆炸了。
个人感觉你的做法是偏向于组合了。
var tree = {
name:'tree'
};
tree.decorate = function() {
alert('Make sure the tree wont\' fall');
};
tree.getDecorator = function(deco) {
tree[deco].prototype = this;
return new tree[deco];
}
tree.RedBalls = function() {
this.decorate = function() {
this.RedBalls.prototype.decorate();
alert('Put on some red balls');
}
}
tree = tree.getDecorator('RedBalls');
tree.decorate();
this.RedBalls.prototype.decorate();这里边的this,指的是什么呢。this.RedBalls也不理解。请教了
个人觉得是tree,但是用hasOwnProperty做测试,又不对应。很奇怪
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
1.在不改变已有代码的前提下, 添加/改变对象功能.
2.代码复用的第二种方式.(另一种方式是继承)