据我了解,当在工厂内部时,我返回一个被注入控制器的对象 . 在服务内部时,我使用 this
处理对象而不返回任何内容 .
我假设服务总是单身,并且每个控制器都会注入 new factory object . 然而,事实证明,工厂对象也是单身人士?
用于演示的示例代码:
var factories = angular.module('app.factories', []);
var app = angular.module('app', ['ngResource', 'app.factories']);
factories.factory('User', function () {
return {
first: 'John',
last: 'Doe'
};
});
app.controller('ACtrl', function($scope, User) {
$scope.user = User;
});
app.controller('BCtrl', function($scope, User) {
$scope.user = User;
});
在 ACtrl
中更改 user.first
时,事实证明 BCtrl
中的 user.first
也发生了变化,例如 User
是单身?
我的假设是在一个带有工厂的控制器中注入了一个新实例?
22 回答
All angular services are singletons :
文档(请参阅单项服务):https://docs.angularjs.org/guide/services
基本上服务和工厂之间的区别如下:
看看这个关于$ offer的演示文稿:http://slides.wesalvaro.com/20121113/#/
这些幻灯片用于AngularJs的一次聚会:http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html
对我来说,当我意识到它们都以相同的方式工作时,就会产生这样的启示:通过运行某些东西 once ,存储它们获得的值,然后在通过依赖注入引用时咳嗽 that same stored value .
说我们有:
三者之间的区别在于:
a
的存储值来自运行fn
,换句话说:fn()
b
的储值来自new
ingfn
,换句话说:new fn()
c
的存储值来自首先通过new
ingfn
获取实例,然后运行实例的$get
方法这意味着,有一些类似于角度内的缓存对象,每次注入的值只分配一次,当它们第一次注入时,其中:
这就是我们在服务中使用
this
并在提供程序中定义this.$get
的原因 .希望这可以帮助 .
这将是了解Service Vs Factory Vs Provider的最佳和简短的答案
资料来源:https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/HuZsOsMvKv4J
这是什么 ben 用 demo http://jsbin.com/ohamub/1/edit?html,output说
“代码中有评论说明了主要区别,但我会在这里稍微扩展一下 . 作为一个说明,我只是想了解这一点,所以如果我说出任何错误,请告诉我 .
Services
Syntax :module.service('serviceName',function);
Result :将serviceName声明为injectable参数时,将提供传递给module.service的实际函数引用 .
Usage :通过简单地将()附加到注入的函数引用来共享对调用有用的实用程序函数可能很有用 . 也可以使用injectArg.call(this)或类似的方式运行 .
Factories
Syntax :module.factory('factoryName',function);
Result :将factoryName声明为injectable参数时,将通过调用传递给module.factory的函数引用来提供返回的值 .
Usage :可以用于返回'class'函数,然后可以新建这个函数来创建实例 .
Providers
Syntax :module.provider('providerName',function);
Result :当将providerName声明为injectable参数时,将通过调用传递给module.provider的函数引用的$ get方法来提供返回的值 .
Usage :可以用于返回一个'class'函数,然后可以将其创建为创建实例,但在注入之前需要某种配置 . 对于可跨项目重用的类可能有用吗?这个还是有些朦胧 . “本
实例
“你好世界”的例子
与
factory
/service
/provider
:还有一种方法可以返回构造函数,这样就可以在工厂中返回 newable 类,如下所示:
所以你可以在一个使用MyObjectWithParam的控制器中完成这个:
在这里看到完整的例子:
http://plnkr.co/edit/GKnhIN?p=preview
在这里谷歌组页面,讨论的地方:
https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ
以下是主要差异:
服务
语法:
module.service( 'serviceName', function );
结果:将serviceName声明为可注入参数时,将向您提供传递给
module.service
的 instance of a function .用法:对于 sharing utility functions 非常有用,只需将()附加到注入的函数引用即可调用 . 也可以使用
injectedArg.call( this )
或类似的方式运行 .工厂
语法:
module.factory( 'factoryName', function );
结果:将factoryName声明为可注入参数时,将提供传递给
module.factory
的 value that is returned by invoking the function reference .用法:可用于返回 'class' 函数,然后可以将其用于创建实例 .
还要检查AngularJS documentation和stackoverflow confused about service vs factory上的类似问题 .
这是example using services and factory . 了解更多关于AngularJS service vs factory的信息 .
添加到第一个答案,我认为.service()适用于以更多面向对象的方式(C#/ Java)编写代码的人(使用此关键字并通过prototype / Constructor函数实例化对象) .
工厂适用于编写代码的开发人员,这些代码对于javascript /功能编码风格更为自然 .
看看angular.js里面的.service和.factory方法的源代码 - 在内部它们都调用provider方法:
非常简单:
.service - 注册函数将作为构造函数调用(又名'newed')
.factory - 注册函数将被调用为一个简单的函数
两次调用都会导致单个对象被注入到应用程序的其他组件中 .
所有提供商的工作方式相同 . 不同的方法
service
,factory
,provider
只是让你在更少的代码中完成同样的事情 .附:还有
value
和constant
.以
provider
开头并以value
结尾的链中的每个特殊情况都有一个附加限制 . 因此,要在它们之间做出决定,你必须问自己哪些让你用更少的代码完成你想要的东西 .这是一张图片,向您展示我的意思:
您可以在博客文章中找到细分和参考指南,我从以下网址获得此图片:
http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/
以下是服务与工厂的更多示例,这些示例可能有助于了解它们之间的差异 . 基本上,一个服务有“new ...”调用它,它已经被实例化了 . 工厂不会自动实例化 .
基本示例
返回具有单个方法的类对象
这是一个具有单一方法的服务:
这是一个返回带有对象的对象的工厂方法:
返回一个值
返回数字列表的工厂:
返回数字列表的服务:
两种情况下的输出都是相同的,即数字列表 .
高级示例
使用工厂的“类”变量
在这个例子中,我们定义了一个CounterFactory,它递增或递减一个计数器,你可以获得当前计数或获取已创建的CounterFactory对象的数量:
我们使用
CounterFactory
来创建多个计数器 . 我们可以访问类变量来查看创建了多少个计数器:此代码的输出是:
“工厂”和“服务”是角度进行DI(依赖注入)的不同方式 .
因此,当我们使用“服务”定义DI时,如下面的代码所示 . 这将创建“Logger”对象的新GLOBAL实例并将其注入函数 .
使用“工厂”定义DI时,它不会创建实例 . 它只是传递方法,后来消费者在内部必须为工厂调用对象实例 .
下面是一个简单的图像,直观地显示了“服务”的DI过程与“工厂”的不同之处 .
当我们想要根据场景创建不同类型的对象时,应该使用工厂 . 例如,取决于我们想要创建简单的“客户”对象的场景,或者具有“地址”对象的“客户”或具有“电话”对象的“客户” . Here is a detailed explanation of this paragraph
应该使用服务当我们有实用程序或共享函数被注入时,如Utility,Logger,Error handler等 .
Service style :(可能是最简单的)返回实际函数:用于共享实用函数,通过简单地将()附加到注入的函数引用来调用它 .
AngularJS中的服务是一个单独的JavaScript对象,它包含一组函数
Factory style :(更多涉及但更复杂)返回函数的返回值:在java中实例化一个对象,如new Object() .
工厂是一个创造 Value 的功能 . 当服务,控制器等需要从工厂注入的值时,工厂按需创建值 . 一旦创建,该值将重用于需要注入的所有服务,控制器等 .
Provider style :(完整版,可配置版)返回函数$ get函数的输出:Configurable .
AngularJS中的提供商是您可以创建的最灵活的工厂形式 . 除了使用provider()函数之外,您可以像使用服务或工厂一样向模块注册提供程序 .
src jenkov
jsbin
jsfiddle
基本区别在于提供程序允许将原始(非对象),数组或回调函数值设置为工厂声明的变量,因此如果返回一个对象,则必须显式声明并返回它 .
另一方面,服务只能用于将服务声明变量设置为对象,因此我们可以避免显式创建和返回对象,而另一方面它允许使用this关键字 .
或简而言之,“提供者是一种更通用的形式,而服务仅限于对象” .
这就是我如何理解它们在设计模式方面的区别:
Service :返回一个类型,该类型将被新建以创建该类型的对象 . 如果使用Java类比,则Service返回 Java Class definition .
Factory :返回可以立即使用的具体对象 . 在Java类比中,工厂返回 Java Object .
经常使人(包括我自己)感到困惑的部分是,当您在代码中注入服务或工厂时,它们可以以相同的方式使用,在两种情况下您在代码中获得的内容都是可以立即调用的具体对象 . 这意味着在服务的情况下,角度代表您在服务声明上调用“新” . 我认为这是一个令人费解的概念 .
AngularJS服务与工厂
将
serviceName
声明为injectable
参数时,将为您提供该函数的实例 . 换句话说,新FunctionYouPassedToService()
. 如果需要,此对象实例将成为AngularJS
注册并稍后注入其他services / controllers
的服务对象 .将
factoryName
声明为injectable
参数时,将为您提供通过调用传递给module.factory
的函数引用返回的值 .在下面的示例中,我们以两种不同的方式定义
MyService
. 注意如何在.service中使用this.methodname
创建服务方法 . 在.factory中,我们创建了一个工厂对象并为其分配了方法 .AngularJS .service
AngularJS .factory
我们可以定义这样的服务:
.service()
是我们模块上的一个方法,它采用名称和定义服务的函数 . 很直接 . 一旦定义,我们就可以在其他组件中注入和使用该特定服务,例如控制器,指令和过滤器,如下所示:现在和工厂一样:
同样,
.factory()
是我们模块上的一个方法,它还有一个名称和一个定义工厂的函数 . 我们可以完全按照与服务相同的方式注入和使用该东西 . 现在这有什么区别?好吧,你可能会看到,而不是在工厂中使用它,我们返回一个对象文字 . 这是为什么?事实证明,服务是构造函数而工厂不是 . 在这个Angular世界的深处,有这个代码在实例化时使用服务构造函数调用Object.create() . 但是,工厂函数实际上只是一个被调用的函数,这就是我们必须显式返回一个对象的原因 .
我有一段时间的困惑,我正在努力在这里提供一个简单的解释 . 希望这会有所帮助!
angular .factory
和angular .service
都用于初始化服务并以相同的方式工作 .The only difference is, how you want to initialize your service.
Both are Singletons
工厂
app.factory(<服务名称>,<带返回值的函数>)
如果您想从 a function that you have with a return value 初始化您的服务,则必须使用此
factory
方法 .例如
When injecting this service (e.g. to your controller):
Angular将 call 您的给定函数(作为
myService()
)返回该对象Singleton - 仅调用一次,存储并传递相同的对象 .
服务
app.service(<服务名称>,<构造函数>)
如果您想从 a constructor function (使用
this
关键字)初始化您的服务,则必须使用此service
方法 .例如
When injecting this service (e.g. to your controller):
Angular会
new
你的给定函数(如new myService()
)返回对象Singleton - 仅调用一次,存储并传递相同的对象 .
注意:如果将
factory
与<constructor function>
或service
与<function with a return value>
一起使用,则无法使用 .示例 - DEMO
Angular Service vs Factory
Angular Service vs Factory (with route)
这要归功于Pascal Precht的博客文章,这有助于我理解其中的差异 .
服务是模块上的一种方法,它采用名称和定义服务的函数 . 您可以在其他组件中注入和使用该特定服务,例如控制器,指令和过滤器 . 工厂是模块上的方法,它还采用名称和函数来定义工厂 . 我们也可以像使用服务一样注入和使用它 .
用new创建的对象使用构造函数的prototype属性的值作为它们的原型,所以我找到了调用Object.create()的Angular代码,我相信它是实例化时的服务构造函数 . 但是,工厂函数实际上只是一个被调用的函数,这就是为什么我们必须返回工厂的对象文字 .
这是我为工厂找到的1.5角度代码:
factory()函数的Angular源代码片段:
它接受传递的名称和工厂函数,并返回一个具有相同名称的提供程序,它具有$ get方法,这是我们的工厂函数 . 每当你向注入器询问特定的依赖关系时,它通过调用$ get()方法基本上要求相应的提供者提供该服务的实例 . 这就是创建提供者时需要$ get()的原因 .
这是用于服务的角度1.5代码 .
事实证明,当我们调用service()时,它实际上调用了factory()!但是,它不仅仅将我们的服务构造函数传递给工厂 . 它还传递一个函数,该函数要求注入器通过给定的构造函数实例化对象 .
换句话说,如果我们在某处注入MyService,代码中会发生以下情况:
要重新进行重新设置,服务会调用工厂,这是相应提供程序上的$ get()方法 . 而且,$ injector.instantiate()是最终使用构造函数调用Object.create()的方法 . 这就是我们在服务中使用“this”的原因 .
对于ES5,无论我们使用哪个:service()或factory(),它总是被调用的工厂,它为我们的服务创建一个提供者 .
尽管如此,您也可以使用相同的服务 . 服务是构造函数,但是,它不会阻止我们返回对象文字 . 因此,我们可以使用我们的服务代码并以一种基本上与我们工厂完全相同的方式编写它,换句话说,您可以将服务编写为工厂以返回对象 .
为什么大多数人建议使用工厂而不是服务?这是我见过的最好的答案,它来自Pawel Kozlowski的书:使用AngularJS掌握Web应用程序开发 .
使用 factory ,您实际上在 factory 内创建 object 并将其返回 .
使用 service ,您只需要 standard function ,它使用
this
关键字来定义函数 .使用 provider ,您定义了
$get
,可以使用 to get 返回数据的对象 .在AngularJS中有三种处理业务逻辑的方法:( Inspired by Yaakov's Coursera AngularJS course ),它们是:
服务
工厂
提供者
在这里我们只谈谈 Service vs Factory
SERVICE :
句法:
app.js
index.html
服务的主要特点:
Lazily Instantiated:如果没有注入服务,它将不会被实例化 . 因此,要使用它,您必须将其注入模块 .
Singleton:如果将它注入多个模块,则所有模块都只能访问一个特定实例 . 这就是为什么在不同控制器之间共享数据非常方便 .
FACTORY
现在让我们来谈谈AngularJS中的工厂
首先让我们来看看语法:
app.js :
现在在控制器中使用以上两个:
工厂特点:
此类服务遵循 factory design pattern . 可以将工厂视为创建新对象或方法的中心位置 .
这不仅可以生成单例,还可以生成可自定义的服务 .
.service()
方法是 factory ,它始终生成相同类型的服务,即单例 . 没有简单的方法来配置它的行为 ..service()
方法通常用作不需要任何配置的快捷方式 .有关简短的解释,请参阅https://stackoverflow.com/a/26924234/5811973 .
有关详细说明,请参阅https://stackoverflow.com/a/15666049/5811973 .
也来自angularJs文档:
你可以理解这个类比的区别 - 考虑一个将返回一些值的普通函数和将使用new keyword实例化的构造函数之间的区别 . 所以创建工厂就像创建将返回一些值的原始函数(原始或一个对象)而创建服务就像创建构造函数(OO类),我们可以使用new关键字创建实例 . 唯一需要注意的是,当我们使用Service方法创建服务时,它将使用AngularJS支持的依赖注入机制自动创建它的实例