Created
November 22, 2013 01:17
-
-
Save dickeylth/7593071 to your computer and use it in GitHub Desktop.
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset=utf-8 /> | |
<title>JS Bin</title> | |
</head> | |
<body> | |
</body> | |
</html> |
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
function decorate(Clazz, decorators){ | |
// 绑定装饰者候选集 | |
Clazz.decorators = decorators; | |
// 核心decorate方法 | |
Clazz.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; | |
} | |
}; | |
// 核心undecorate方法 | |
Clazz.prototype.undecorate = function(decorator){ | |
var list = this.decoratorList, | |
decoratorObj = Clazz.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); | |
} | |
this.parent = iterator; | |
break; | |
} | |
iterator = iterator.parent; | |
} | |
return this; | |
}; | |
Clazz.prototype.undecorate2 = function(decorator){ | |
var list = this.decoratorList, | |
decoratorObj = Clazz.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; | |
}; | |
} | |
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('超级玛丽在跳跃'); | |
}; | |
// 装饰器 | |
var decorators = { | |
'mushroom': { | |
getHeight: function(){ | |
return this.parent.getHeight() + 10; | |
}, | |
getBlood: function(){ | |
return this.parent.getBlood() + 1; | |
} | |
}, | |
'flower': { | |
getColor: function(){ | |
return 'white'; | |
}, | |
attack: function(){ | |
return '超级玛丽吐火力弹!'; | |
} | |
} | |
}; | |
decorate(SuperMario, decorators); | |
// 调用 | |
var superMario = new SuperMario(); | |
superMario = superMario.decorate('mushroom'); | |
console.log("吃了红蘑菇,超级玛丽变身了,长到" + superMario.getHeight() + "了, 血变成" + superMario.getBlood() + "滴了"); | |
superMario = superMario.decorate('flower'); | |
console.log("吃了火力花,再次华丽变身,变成" + superMario.getColor() + "了,能战斗了:" + superMario.attack()); | |
console.log("完全装饰完毕"); | |
console.log(superMario); | |
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