Service vs Factory vs provider的迷惑

剛開始我很迷惑的,可是通過一段時間的項目,還有看大漠老師的東西,彷佛明白了,他們的區別也就是  一我的喜歡吃麪仍是吃飯或者肯德基區別。目的就是填飽肚子!javascript

如下是它們在AngularJS源代碼中的定義:java

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的構造函數中建立了一個新的實例。app

如下是一個例子,展現了一個service和一個factory如何完成相同的事情:ide

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提供了更多的靈活性,由於它能夠返回函數,這些函數以後能夠被新建出來。這迎合了面向對象編程中工廠模式的概念,工廠能夠是一個可以建立其餘對象的對象。this

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的值。spa

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在設計一個包含不少私有方法的類時也頗有用:code

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中更容易。

相關文章
相關標籤/搜索