網路上有很多 Service vs Factory 的文章,最常看到的說法是 Service 是用 new 來建立的,而 Factory 是回傳 return 定義的值。
然後後面附上一長串看的霧煞煞的解釋文。
WHAT!???
我看了很多解釋後,最後有點小心得。也用自己的文字解釋一下~
先寫簡單的寫 Factory 跟 Service 範例:
以下的 Factory 跟 Service Dependency Injection (DI) 注入後所取用行為都是一樣。
範例:http://plnkr.co/edit/4BaT54BytV65EYsQUijq
angular.module('myExample', [])
.controller('myCtrl', function($scope, LuffyFactory, LuffyService) {
// 一樣的取用方式
console.log('LuffyFactory', LuffyFactory.word); // 我要成為海賊王
console.log('LuffyService', LuffyService.word); // 一樣~
});
// factory
angular.module('myExample')
.factory('LuffyFactory', function () {
var factory = { };
factory.word = '我要成成海賊王!';
return factory;
})
// service
angular.module('myExample')
.service('LuffyService', function () {
this.word = '我要成為海賊王!';
})
Factory 的行為很簡單,Controller 注入Factory 取得的物件就是被 factory object ({}) 包起來並且 return 的物件。
也就是說,假如沒有被 { } 包起來值都不會被外面取得。
(p.s. 不一定要 return object, 任何 type 都可以)
可改寫上面的範例,
angular.module('myExample')
.factory('LuffyFactory', function () {
// 這裡可以放 private value,外面無法取得
var value = “Hello, 我是 private 值”;
return {
word: '我要成成海賊王!';
}
})
Service 是把東西存在 this 裡面,像是我們平常在製作 constructor 一樣。
以上範例假如寫成 constructor 就會是
function LuffyService () {
this.word = '我要成為海賊王!';
}
AngularJS 在初始化的時候,會幫我們把 new LuffyService() 這個動作完成。
所以當 controller 要求注入 LuffyService 的時候,AngularJS 就會把已經 new 過的的 LuffyService 給 controller。
回顧一下上篇文章說的,
Provider 都是 singleton。
Provider 都是 singleton。
Provider 都是 singleton。(很重要,所以說三次)
沒錯,所以就算 Service 有 new 這個指令,可是其實也只是做一次而已。
每個要求注入 Service 的 components 拿到的都會是同一個 Service reference。
Factory 也是相同的情況,全部系統共用一個 Factory reference。
來個簡單的例子證明。
範例:http://plnkr.co/edit/PfAwdHbKpsfIF3Aywwgu
兩個 controllers 同時注入相同名稱的 Service 跟 Factory,會發現兩個 controllers 的 Service 跟 Factory 回傳的 ID 都會一樣。
我個人最常使用 Factory 跟 Service singleton 的特性來儲存共用資料,讓系統裡不同的 components 都可以修改取得相同的資料來源。
Provider:
來簡單的說明一下 Provider 跟 Factory 和 Service 的關係。
個人覺得 Mark Meyer 在 top 10 mistakes angularjs developers make 文章解說的很好。
把 code 借來並附上我的註解。
// factory 的底層就是回傳 provider 的 $get 裡的值
function factory(name, factoryFn) {
return provider(name, { $get: factoryFn });
}
// service 的底層就是在 factory 裡使用 $jnjector.instantiate 跟 construct 建立新物件
// ( $injector.instantiate 會做 new instance 的動作)
function service(name, constructor) {
return factory(name, ['$injector',
function($injector) {
return $injector.instantiate(constructor);
}]);
}
目前我都可以用 Factroy 跟 Service 來實作我想要的功能,先少使用 Provider。(大概一次吧)
所以 Provider 的使用方式我就跳過了...
有興趣的朋友推薦看 Chang Yuntai 大大寫的 「AngularJS Service, Factory, Provider 差別」好文!
或是參考下面的文章~
參考文章:
AngularJS Providers Documentation
StackOverFlow: service vs provider vs factory