刚开始我很迷惑的,但是经过一段时间的项目,还有看大漠老师的东西,似乎明白了,他们的区别也就是 一个人喜欢吃面还是吃饭或者肯德基区别。目的就是填饱肚子!
以下是它们在AngularJS源代码中的定义:
1 2 3 4 5 6 7 8 9 | function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } function service(name, constructor) { return factory(name, [ '$injector' , function ($injector) { return $injector.instantiate(constructor); }]); } |
从源代码中你可以看到,service仅仅是调用了factory函数,而后者又调用了provider函数。事实上,AngularJS也为一些值、常量和装饰提供额外的provider封装,而这些并没有导致类似的困惑,它们的文档都非常清晰。
由于service仅仅是调用了factory函数,这有什么区别呢?线索在$injector.instantiate:在这个函数中,$injector在service的构造函数中创建了一个新的实例。
以下是一个例子,展示了一个service和一个factory如何完成相同的事情:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var app = angular.module( 'app' ,[]); app.service( 'helloWorldService' , function (){ this .hello = function () { return "Hello World" ; }; }); app.factory( 'helloWorldFactory' , function (){ return { hello: function () { return "Hello World" ; } } }); |
当helloWorldService或helloWorldFactory被注入到控制器中,它们都有一个hello方法,返回”hello world”。service的构造函数在声明时被实例化了一次,同时factory对象在每一次被注入时传递,但是仍然只有一个factory实例。所有的providers都是单例。
既然能做相同的事,为什么需要两种不同的风格呢?相对于service,factory提供了更多的灵活性,因为它可以返回函数,这些函数之后可以被新建出来。这迎合了面向对象编程中工厂模式的概念,工厂可以是一个能够创建其他对象的对象。
1 2 3 4 5 6 7 8 9 | app.factory( 'helloFactory' , function () { return function (name) { this .name = name; this .hello = function () { return "Hello " + this .name; }; }; }); |
这里是一个控制器示例,使用了service和两个factory,helloFactory返回了一个函数,当新建对象时会设置name的值。
1 2 3 4 5 6 7 8 9 | app.controller( 'helloCtrl' , function ($scope, helloWorldService, helloWorldFactory, helloFactory) { init = function () { helloWorldService.hello(); //'Hello World' helloWorldFactory.hello(); //'Hello World' new helloFactory( 'Readers' ).hello() //'Hello Readers' } init(); }); |
在初学时,最好只使用service。
Factory在设计一个包含很多私有方法的类时也很有用:
1 2 3 4 5 6 7 8 9 10 11 | app.factory( 'privateFactory' , function (){ var privateFunc = function (name) { return name.split( "" ).reverse().join( "" ); //reverses the name }; return { hello: function (name){ return "Hello " + privateFunc(name); } }; }); |
通过这个例子,我们可以让privateFactory的公有API无法访问到privateFunc方法,这种模式在service中是可以做到的,但在factory中更容易。