Skip to content

Instantly share code, notes, and snippets.

@dickeylth
Created November 22, 2013 01:12
Show Gist options
  • Save dickeylth/7593005 to your computer and use it in GitHub Desktop.
Save dickeylth/7593005 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
</body>
</html>
function SuperMario(){
this.name = '超级玛丽';
this.height = 10;
this.blood = 0;
this.color = 'green';
this.decoratorList = [];
}
SuperMario.prototype.getHeight = function(){
return this.height;
};
SuperMario.prototype.getBlood = function(){
return this.blood;
};
SuperMario.prototype.getColor = function(){
return this.color;
};
SuperMario.prototype.run = function(){
console.log('超级玛丽在奔跑');
};
SuperMario.prototype.jump = function(){
console.log('超级玛丽在跳跃');
};
// 装饰器
SuperMario.decorators = {
'mushroom': {
getHeight: function(){
return this.parent.getHeight() + 10;
},
getBlood: function(){
return this.parent.getBlood() + 1;
}
},
'flower': {
getColor: function(){
return 'white';
},
attack: function(){
return '超级玛丽吐火力弹!';
}
}
};
// 装饰方法
SuperMario.prototype.decorate = function(decorator){
var Decorator = function(){},
overrides = this.constructor.decorators[decorator],
list = this.decoratorList,
i, newobj;
if(list.indexOf(decorator) == -1){
this.decoratorList.push(decorator);
Decorator.prototype = this;
newobj = new Decorator();
newobj.parent = Decorator.prototype;
for(i in overrides){
if(overrides.hasOwnProperty(i)){
newobj[i] = overrides[i];
}
}
return newobj;
}
};
// 移除装饰方法
SuperMario.prototype.undecorate = function(decorator){
var list = this.decoratorList,
decoratorObj = SuperMario.decorators[decorator],
decoratedMethods = [],
iterator = this,
len = list.length,
i, methodLength;
for(i in decoratorObj){
decoratedMethods.push(i);
}
while(len-- >= 0){
if(list[len] == decorator){
this.decoratorList.splice(len, 1);
for(i = 0, methodLength = decoratedMethods.length; i < methodLength; i++){
delete iterator[decoratedMethods[i]];
var prevProto = Object.getPrototypeof(iterator);
delete prevProto[decoratedMethods[i]];
Object.setPrototypeof(iterator, prevProto);
//delete iterator.__proto__[decoratedMethods[i]];
}
this.parent = iterator;
break;
}
iterator = iterator.parent;
}
return this;
};
// 移除装饰方法2
SuperMario.prototype.undecorate2 = function(decorator){
var list = this.decoratorList,
decoratorObj = SuperMario.decorators[decorator],
Decorator = function(){},
afterCursor = this, prevCursor = this.parent,
len = list.length,
i, newObj;
while(len-- >= 0){
if(list[len] == decorator){
this.decoratorList.splice(len, 1);
if(afterCursor){
for(i in afterCursor){
if(afterCursor.hasOwnProperty(i) && !(i in decoratorObj) && (i != 'parent')){
prevCursor[i] = afterCursor[i];
}
}
}
Decorator.prototype = prevCursor;
break;
}
afterCursor = prevCursor;
prevCursor = prevCursor.parent;
}
if((list.length === 0) || (len === list.length)){
// 如果所有的decorator都被清掉了或者清掉的是末尾的decorator,直接返回留下的merge过的prevCursor
newObj = prevCursor;
}else{
// 如果还有decorator,再mix上当前对象的对象属性
newObj = new Decorator();
for(i in this){
if(this.hasOwnProperty(i) && (i != 'parent')){
newObj[i] = this[i];
}
}
// parent指向merge后的prevCursor
newObj.parent = prevCursor;
}
return newObj;
};
// 调用
var superMario = new SuperMario();
superMario = superMario.decorate('mushroom');
console.log("吃了红蘑菇,超级玛丽变身了,长到" + superMario.getHeight() + "了, 血变成" + superMario.getBlood() + "滴了");
superMario.age = 12;
superMario = superMario.decorate('flower');
console.log("吃了火力花,再次华丽变身,变成" + superMario.getColor() + "了,能战斗了:" + superMario.attack());
superMario = superMario.undecorate2('mushroom');
console.log("超级玛丽中枪了。。。红蘑菇失效了,身高:" + superMario.getHeight() + ", 还剩" + superMario.getBlood() + "滴血,颜色:" + superMario.getColor());
console.log("还能战斗吗:" + (typeof superMario.attack == 'function'));
superMario = superMario.undecorate2('flower');
console.log("超级玛丽中枪了。。。火力花也失效了,身高:" + superMario.getHeight() + ", 还剩" + superMario.getBlood() + "滴血,颜色:" + superMario.getColor());
console.log("还能战斗吗:" + (typeof superMario.attack == 'function'));
console.log(superMario);
var superMario2 = new SuperMario();
superMario2 = superMario2.decorate('mushroom');
superMario2 = superMario2.decorate('flower');
superMario2 = superMario2.undecorate2('flower');
console.log(superMario2);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment