【问题标题】:Must the module pattern really be singleton?模块模式真的必须是单例的吗?
【发布时间】:2014-09-11 17:26:45
【问题描述】:

模块模式被大多数人描述为:

var module = (function() {
     // private fields
     var a, b, c;

     // private functions
      function myFunction() {}

     // public data (where you expose to outside)
     return {
       publicFunc:  function() {}
     };
})();

但是上面的代码创建了模块的一个实例。真的必须是单例吗?

下面的代码还是模块模式吗?

function module() {

   // same code

   return {
       publicFunc:  function() {}
     };
 }

【问题讨论】:

  • 是的,一个模块应该是一个单例,创建一个模块的多个实例并没有什么意义,因为它实际上只是一个“帮助”函数,其中包含可以调用的方法等。重点只是创建一个具有私有作用域的闭包,这样模块就不会干扰其他代码。第二个例子不是模块,它只是一个返回对象的函数。
  • 不,但它确实有资格将其用作具有公共和私有变量的“类”。

标签: javascript design-patterns


【解决方案1】:

是的,模块模式返回一个单例,但这并不是一个实际的限制。您可以使用模块模式返回单例工厂函数,然后多次调用该工厂函数。

var point = (function() {
  // Add private code here to make use of module pattern.
  // If you don't have anything to keep private, then
  // module pattern is overkill, as noted in the comments
  return function(x,y) {
    return { 
      x : x,
      y: y
    }
  }
})();

var point1 = point(0,0);
var point2 = point(3,4);

不使用工厂函数,您也可以将模块模式放入循环中并多次执行(不推荐这样做,因为它非常低效):

var points = [];
for (var i=0; i<4; i++){
  points[i] = (function module() {
    // same code
    return {
      publicFunc:  function() {}
    };
  })();
}

更新:根据@North 和@Bergi 下面的反馈在第一个示例中添加了评论

【讨论】:

  • +1,你应该考虑在你的例子中使用模块范围。
  • 您的单例工厂功能已经过时了。你应该让事情尽可能简单。你也可以写成var point = function(x, y) { return {x: x, y: y}; };
  • @North。是的,但是过度工程是回答有关模块模式的原始帖子。我会对此添加评论。
  • 模块模式的要点是拥有私有状态,您只能使用您在返回对象中公开的函数来更改该状态。您很少需要在模块的所有实例之间共享状态。通常您对实例感兴趣以拥有自己的状态。但我确实知道你来自哪里(模块 = 单例)。
【解决方案2】:

是的,模块是单例的。一辆车只有一个引擎。创建第二个根本没有意义(除非您从根本上改变整个设计,增加任何支柱可以承受的负载等)。

第二种模式是“类”模式,其中有许多行为相似的实例(想想一堆汽车)。

【讨论】:

  • 不过,您可以使用模块模式来创建类。
  • @Bergi:这不太正确。您可以在模块模式中包含类模式。但是类和模块模式是不同的东西,旨在实现不同的目标。您不应将两者混为一谈(无论是在代码中还是在谈论它们时)以避免混淆。
  • 好吧,我承认这可能会让人们感到困惑,但你可以(并且经常这样做:examplebetter examplereally large example)混合它们。它仍然是一个单身人士:你的公司只有一个电机厂。
  • 这就是我的观点。第一个示例是类模式,而不是模块。在 JavaScript 中,两者之间没有明显的区别,因此代码按照描述的内容执行是很重要的。否则,您的心智模型会导致您在开始调试时使用错误的期望。
  • 我的心智模型包括first-class 类,所以没问题:-)
【解决方案3】:

我一直认为模块模式是非单例版本。事实上,我确实尽可能避免使用单例,尤其是在它们有状态的情况下。从测试的角度来看,它们是一场噩梦,尤其是在编写为自调用函数时。

对我来说,模块模式就是封装状态。如果我只使用模块的单个实例,我就称它为单例模块。

Here 是一篇抓住了要点的文章,至少我是这么看的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    • 2022-11-06
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多