Javascript AngularJS设计模式:我应该使用工厂来创建构造函数吗?

Javascript AngularJS设计模式:我应该使用工厂来创建构造函数吗?,javascript,design-patterns,angularjs,Javascript,Design Patterns,Angularjs,这是我在创建AngularJS应用程序时一直在思考的问题。当我第一次了解AngularJS工厂时,我认为它们的一个聪明用法是创建并返回构造函数,而不是普通对象,例如: app.factory("Foo", function() { function Foo(bar, baz) { this.bar = bar; this.baz = baz; ... } Foo.prototype = { constructor: Foo, method1:

这是我在创建AngularJS应用程序时一直在思考的问题。当我第一次了解AngularJS工厂时,我认为它们的一个聪明用法是创建并返回构造函数,而不是普通对象,例如:

app.factory("Foo", function() {
  function Foo(bar, baz) {
    this.bar = bar;
    this.baz = baz;
    ...
  }

  Foo.prototype = {
    constructor: Foo,
    method1: function() { ... },
    method2: function() { ... },
    ...,
    methodn: function() { ... },
  };

  return Foo;
});
然后,您可以将该函数注入控制器,并使用
new
调用它。我发现这在美学上是令人愉悦的,但现在我开始认为这实际上是一种反模式。问题是,当您在AngularJS感知的上下文中工作时,它工作得很好,但是一旦您想要,例如,从控制台调用构造函数,在Web Worker中使用它,或者在非AngularJS应用程序中重用代码,您就必须开始围绕AngularJS工作,而不是使用它。我开始怀疑这种方法是否被误导了,因为javascript中的函数似乎已经是“单例函数”,并且似乎不需要任何帮助进行实例化

我是否误用了AngularJS工厂?使用暴露于全局范围的构造函数会更好吗?更一般地说,是否有特定的因素促使AngularJS工厂/服务/提供商的使用超过全局对象,或者反之亦然?

是的

工厂语法:module.factory('factoryName',function);结果: 将factoryName声明为可注入参数时,您将 提供通过调用函数引用返回的值 传递到module.factory用法:可用于返回 “类”函数,然后可以对其进行新建以创建实例。

资料来源:


上面的链接也被用作注释的来源:

在Angular和Javascript的上下文中,这可能是一个很好且方便的用法(它恰好允许对构造函数和对象原型进行令人难以置信的操作),但是,在我看来,它有点与经典的工厂模式逻辑相矛盾

Factory用于在其内部构造新对象,应用一些配置、初始化并将依赖项注入到新创建的对象中,如Factory设置中所指定(如果有)

例如,您可以要求工厂创建一个存储连接,工厂创建一个MySQL连接、SQLite连接或Redis连接——只要构造的对象实现了一些接口(或者在Javascript上下文中使用duck类型——如果它像鸭子一样嘎嘎叫,那么它就是鸭子),您的控制器就不在乎了

但是如果你在给工厂外的工厂打电话后使用了
new
关键字,那就好像你说了下面的话:

“嘿,工厂,给我一个项目的原型(构造器),我会自己创建项目。”

因此,在这种情况下,您的工厂不是一个用于创建新对象的“经典工厂”,而是一个原型工厂,它有一个原型可提供给所有调用者,以便他们自己可以制造新对象


当您有没有任何参数的简单构造函数时,您可能不会介意,但在经典示例中(存储连接)工厂的这种使用是没有意义的,因为工厂的调用方必须完成工厂的工作-将配置和依赖项注入到新创建的对象中。

而不是短路依赖项注入容器提供的依赖项解析值,我建议在Angular文档中通过$provide.decorator(…)查看decorator模式对OOTB的支持。公开一个原型并不是“邪恶的”,但是当你对一个有依赖关系的组件调用“新建”时,我不确定你会得到什么,也许除了基于上下文的可配置原型。如果这就是您想要的,那么您可以使用$inject.get('myWhatever')将其转换为服务定位器。这不是一个好主意。工厂的理念是提供价值,而不必担心它是如何建造的。