在JavaScript中,我想在长时间运行的应用程序中实例化一个对象。该对象应该允许自己使用mixins进行扩充。有一些设计限制:
在JS中,通常mixins将他们的方法直接复制到一个对象上。如果您不想轻易拔掉新行为,这很好。我们的想法是,这些行为应该很容易随时添加或删除,因为应用程序可以无限期地运行,并且使用对象来添加行为并不会使以后删除它变得简单。
我指的是'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将提供一个允许这样做的代理,但我想知道我是否可能错过了一个更简单的方法。
哪些设计模式或机制可以轻松添加以后易于删除的插件行为?任何框架都可以按照这些方式做点什么吗?
答案 0 :(得分:0)
我之前创建了一个名为Uberproto的ES5继承库,它允许您将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'
所以你需要做的就是将这个功能包装成更通用的东西。