在 JavaScript 中,我想在长时间运行的应用程序中实例化一个对象。该对象应该允许使用 mixins 来增强自身。有一些设计限制:
- mixin 可能会覆盖现有方法
- mixin 可以提供新方法
- 给定的 mixin 方法应该能够引用 super,从而允许跨多个 mixin 的类似命名行为通过管道连接在一起
- 从对象中删除 mixin 应该不会比添加 mixin 更难
- 我想将 mixins 插入对象中。也就是说,我希望不要包装/装饰该对象,因为该对象已经过时了对原始对象的引用。
在 JS 中,通常 mixin 将它们的方法直接复制到对象上。如果您不想轻易取消新行为,这很好。我们的想法是,这些行为应该易于随时添加或删除,因为应用程序可能无限期地运行,并且使用对象来添加行为并不会让以后删除它变得整洁和容易。
我指的是“mixins”。主要思想是对象可以插入或拔出可以通过管道连接在一起的行为;机制本身并不那么重要。你们中有些人可能熟悉 Rack知道这有多么有用。
var tim = new Person('Tim'); //at 12:00pm
tim.eat() //at 12:00pm -- native Person behavior
tim.addBehavior(husband) //at 12:00pm
tim.kissWife() //at 12:00pm -- husband behavior
tim.addBehavior(father) //at 12:00pm
tim.addBehavior(hungry) //at 12:00pm -- augments the native eat behavior
tim.addBehavior(bowler) //at 5:00pm
tim.bowl() //at 5:00pm
tim.performDailyDuties() //at 5:00pm -- includes husband and father duties
tim.removeBehavior(bowler) //at 5:00pm -- easily remove behavior
tim.bowl() //at 5:01pm -- error!
tim.kissWife() //at 5:01pm
我不想...
var husbandTim = new Husband(tim)
var bowlerTim = new Bowler(husbandTim)
...因为它使得消除一种特定行为变得困难。另外,所有引用 tim
的地方又如何呢?这些地方不会意识到新行为。
不幸的是,JS 没有提供任何我所知道的东西来使这变得容易。 ES6 将提供一个代理来实现这一点,但我想知道我是否可能错过了一个更简单的方法。
哪些设计模式或机制可以使添加插件行为变得容易,并且以后也可以轻松删除?是否有框架按照这些思路做一些事情?
最佳答案
我不久前创建了一个 ES5 继承库,名为 Uberproto这确实允许您向对象添加 mixins 并调用覆盖的方法。例如:
var PersonObject = {
init : function(name) {
this.name = name;
},
fullName : function() {
return this.name;
}
};
Proto.mixin({
fullName : function() {
return 'My name is: ' + this._super();
}
}, PersonObject);
// Create a plain object without calling the constructor
var instance = Object.create(PersonObject);
instance.name = 'Dude';
console.log(instance.fullName()); // 'My name is: Dude'
我发现,如果你小心创建 mixins 的目的,它实际上效果很好。我从来不需要删除 mixin,但它应该像在添加原始方法之前存储对原始方法的引用一样简单:
var PersonObject = {
init : function(name) {
this.name = name;
},
fullName : function() {
return this.name;
}
};
var backup = {
fullName: PersonObject.fullName
};
Proto.mixin({
fullName : function() {
return 'My name is: ' + this._super();
}
}, PersonObject);
// Create a plain object without calling the constructor
var instance = Object.create(PersonObject);
instance.name = 'Dude';
console.log(instance.fullName()); // 'My name is: Dude'
// Restore old mixin
PersonObject.fullName = backup.fullName;
var instance = Object.create(PersonObject);
instance.name = 'Dave';
console.log(instance.fullName()); // 'Dave'
因此,您需要做的就是将该功能包装成更通用的东西。
关于JavaScript:将行为插入对象并轻松删除这些行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16364969/