如何编写符合 'open closed principle' 的工厂函数
How to write factory functions that adhere to the 'open closed principle'
我一直在研究在 JavaScript 中使用工厂函数作为构造函数的替代方法。我的大部分研究都源于 Eric Elliot 在其博客文章中提供的信息,例如:
http://ericleads.com/2012/09/stop-using-constructor-functions-in-javascript
虽然我同意这里所说的大部分内容,但我确实怀念构造函数的自动初始化方面,所以我想在我的工厂函数中实现类似的东西:
var myFactory = function (options) {
var inst = _.create({
initialize : function (options) {
var allowedProps = ['name', 'type'];
this.options = options;
_.extend(this, _.pick(options, allowedProps));
},
test : function () {
if(this.type === 'alpha') {
return true;
}
return false;
}
})
inst.initialize.call(inst, options);
return inst;
};
var x = myFactory({ name : 'shiny', type : 'alpha' });
var y = myFactory({ name : 'happy', type : 'beta' });
1) 这种行为本身是否只是重新引入构造函数带来的一些问题?
2) 在初始化方法中使用 'options' 扩展实例是否违反了 Open/Closed 原则?它是开放扩展的(它可以用作原型)但我也可以通过 'options' 修改原型本身。
我对这种模式有一种不好的感觉,觉得我应该将初始化的最终控制权交给消费者。它深受 Backbone 依赖于构造函数的扩展方法的启发。
进一步阅读:
https://tsherif.wordpress.com/2013/08/04/constructors-are-bad-for-javascript/
1) Is this behavior itself just re-introducing some of the problems that come with constructors?
没有,虽然是重新引入构造函数。只需将 initialize
换成 constructor
,您就会得到几乎相同的结果。只有非常单一的语法:-)
2) Am I violating the Open/Closed principle by extending the instance with 'options' within the initialize method?
不,这篇文章说明构造函数如何破坏 open/closed 原则的要点是,为了将它们换成不同的工厂,您必须删除整个代码中的 new
(在事实上你不知道)。但是,如果您扩展 class,则不必更改其调用。
I've got a bad feeling about this pattern and feel like I should be giving ultimate control of initialization to the consumer.
好吧,如果你想这样做,只需删除初始化程序并让消费者执行 extend
:
var x = _.extend(myFactory(), { name : 'shiny', type : 'alpha' });
var y = _.extend(myFactory(), { name : 'happy', type : 'beta' });
我一直在研究在 JavaScript 中使用工厂函数作为构造函数的替代方法。我的大部分研究都源于 Eric Elliot 在其博客文章中提供的信息,例如:
http://ericleads.com/2012/09/stop-using-constructor-functions-in-javascript
虽然我同意这里所说的大部分内容,但我确实怀念构造函数的自动初始化方面,所以我想在我的工厂函数中实现类似的东西:
var myFactory = function (options) {
var inst = _.create({
initialize : function (options) {
var allowedProps = ['name', 'type'];
this.options = options;
_.extend(this, _.pick(options, allowedProps));
},
test : function () {
if(this.type === 'alpha') {
return true;
}
return false;
}
})
inst.initialize.call(inst, options);
return inst;
};
var x = myFactory({ name : 'shiny', type : 'alpha' });
var y = myFactory({ name : 'happy', type : 'beta' });
1) 这种行为本身是否只是重新引入构造函数带来的一些问题?
2) 在初始化方法中使用 'options' 扩展实例是否违反了 Open/Closed 原则?它是开放扩展的(它可以用作原型)但我也可以通过 'options' 修改原型本身。
我对这种模式有一种不好的感觉,觉得我应该将初始化的最终控制权交给消费者。它深受 Backbone 依赖于构造函数的扩展方法的启发。
进一步阅读:
https://tsherif.wordpress.com/2013/08/04/constructors-are-bad-for-javascript/
1) Is this behavior itself just re-introducing some of the problems that come with constructors?
没有,虽然是重新引入构造函数。只需将 initialize
换成 constructor
,您就会得到几乎相同的结果。只有非常单一的语法:-)
2) Am I violating the Open/Closed principle by extending the instance with 'options' within the initialize method?
不,这篇文章说明构造函数如何破坏 open/closed 原则的要点是,为了将它们换成不同的工厂,您必须删除整个代码中的 new
(在事实上你不知道)。但是,如果您扩展 class,则不必更改其调用。
I've got a bad feeling about this pattern and feel like I should be giving ultimate control of initialization to the consumer.
好吧,如果你想这样做,只需删除初始化程序并让消费者执行 extend
:
var x = _.extend(myFactory(), { name : 'shiny', type : 'alpha' });
var y = _.extend(myFactory(), { name : 'happy', type : 'beta' });