【问题标题】:The Revealing Module Pattern (RMP) disadvantages显示模块模式 (RMP) 的缺点
【发布时间】:2012-12-12 14:40:58
【问题描述】:

我最近熟悉了显示模块模式 (RMP),并且阅读了很多关于它的文章。

这似乎是一个非常好的模式,我想开始在一个大项目中使用它。在我正在使用的项目中:Jquery、KO、requireJS、Jquery Mobile、JayData。在我看来,它非常适合 KO ViewModel。

具体来说,我想使用它的THIS 版本。

我找不到使用这种模式的缺点,是因为没有任何缺点(我很难相信)?

在开始使用之前我应该​​考虑什么?

【问题讨论】:

标签: javascript design-patterns knockout.js revealing-module-pattern


【解决方案1】:

显示模块模式 (RMP) 创建的对象在覆盖方面表现不佳。因此,使用 RMP 制作的对象不能很好地用作原型。因此,如果您使用 RMP 创建将在继承链中使用的对象,请不要这样做。 这个观点是我自己的观点,与那些揭示原型模式的支持者相反。

要查看不良继承行为,请使用以下 url 构建器示例:

function rmpUrlBuilder(){
  var _urlBase = "http://my.default.domain/";
  var _build = function(relUrl){
    return _urlBase + relUrl;
  };

  return {
    urlBase: _urlBase,
    build: _build
  }
}

抛开为什么你会为没有私有组件的对象使用 RMP 的问题,请注意,如果你获取返回的对象并用“http://stackoverflow.com”覆盖 urlBase,你会期望 build() 的行为会改变适当地。它没有,如下所示:

var builder = new rmpUrlBuilder();
builder.urlBase = "http://stackoverflow.com";
console.log(builder.build("/questions"); // prints "http://my.default.domain/questions" not "http://stackoverflow.com/questions"

将行为与以下 url builder 实现进行对比

function urlBuilder = function(){
  return {
    urlBase: "http://my.default.domain/".
    build: function(relUrl){ return this.urlBase + relUrl;}
  }
}

var builder = new urlBuilder();
builder.urlBase = "http://stackoverflow.com";
console.log(builder.build()); // prints "http://stackoverflow.com/questions"

行为正确。

您可以通过使用此范围来纠正显示模块模式的行为,如下所示

function rmpUrlBuilder(){
  var _urlBase = "http://my.default.domain/";
  var _build = function(relUrl){
    return this.urlBase + relUrl;
  };

  return {
    urlBase: _urlBase,
    build: _build
  }
}

但这反而违背了显示模块模式的目的。更多详情请看我的博文http://ilinkuo.wordpress.com/2013/12/28/defining-return-object-literals-in-javascript/

【讨论】:

  • 这是一个寻找问题的答案。它的例子是人为的,它称正确的行为是坏的,它称预期的行为是意外的。 OP 写了一系列关于这个主题的长答案,他们都面临同样的问题,他坚决捍卫他的答案,反对任何指出这些问题的人。 “你一定不明白这些例子。”但是七年过去了,这些答案是人们在搜索揭示模块模式时所找到的答案。
【解决方案2】:

我阅读了@nemesv 引用我的文章(谢谢:)),我认为还有一个没有提到的缺点,所以我想我会在这里添加它以供参考。以下是文章的引述:

缺点

这种模式的一个缺点是,如果私有函数引用 一个公共函数,如果一个补丁,这个公共函数不能被覆盖 有必要的。这是因为私有函数将继续 参考私有实现,该模式不适用于 公共成员,仅限函数。

引用私有变量的公共对象成员也是 受上述无补丁规则说明的约束。

因此,使用 Revealing Module 模式创建的模块 可能比使用原始模块创建的更脆弱 模式,所以在使用过程中要小心。

还有我的补充:

您不能在此模式中使用继承。例如:

var Obj = function(){
    //do some constructor stuff
}

var InheritingObj = function(){
    //do some constructor stuff
}

InheritingObj.prototype = new Obj();

InheritingObj.prototype.constructor = InheritingObj;

这是一个在 js 中继承的简单示例,但是当使用 Revealing Prototype Pattern(归档 here)时,您需要这样做:

InheritingObj.prototype = (function(){
    //some prototype stuff here
}());

这将覆盖您的继承。

【讨论】:

  • 它似乎与 Object.create(urlBuilder);进行继承的另一种方式是这种方式jsfiddle.net/d0n7kfmx你怎么看?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-19
  • 2020-01-23
  • 2016-05-15
  • 1970-01-01
相关资源
最近更新 更多