前言
这段时间对AngularJS十分感兴趣,留意到Angular中有两个特性:service and factory ,用法看起来都差不多一样的,不知道有什么异同。
示例代码
<html ng-app="myApp">
<script id="others_angular_103" type="text/javascript" class="library" src="/js/sandbox/other/angular.min.js"></script>
<head></head>
<body ng-app="myApp">
<div ng-controller="HelloCtrl">
<p>{{fromService}}</p>
<p>{{fromFactory}}</p>
</div>
<br />
<div ng-controller="GoodbyeCtrl">
<p>{{fromService}}</p>
<p>{{fromFactory}}</p>
</div>
</body>
</html>
var app = angular.module('myApp',[]);
app.service('reverseService',function(){
this.reverse = function(text){
return text.split(" ").reverse().join(" ");
}
});
app.factory('testFactory', function(){
return {
sayHello: function(text){
return "Factory says \"Hello " + text + "\"";
},
sayGoodbye: function(text){
return "Factory says \"Goodbye " + text + "\"";
}
}
});
app.service('testService', function(){
this.sayHello= function(text){
return "Service says \"Hello " + text + "\"";
};
this.sayGoodbye = function(text){
return "Service says \"Goodbye " + text + "\"";
};
});
function HelloCtrl($scope, testService, testFactory)
{
$scope.fromService = testService.sayHello("World");
$scope.fromFactory = testFactory.sayHello("World");
}
function GoodbyeCtrl($scope, testService, testFactory)
{
$scope.fromService = testService.sayGoodbye("World");
$scope.fromFactory = testFactory.sayGoodbye("World");
}
用法几乎完全一样。但是 service 写起来更简单点,看起来更简洁一点。
异同
但是这并不能说明两者的不同,再看看下面的代码 :
app.service('reverseService',function(){
this.reverse = function(text){
return text.split(" ").reverse().join(" ");
}
});
app.factory('testFactory',['$window', function(win){
return {
sayHello: function(text){
win.alert('hello,I am factory!!')
return "Factory says \"Hello " + text + "\"";
},
sayGoodbye: function(text){
return "Factory says \"Goodbye " + text + "\"";
}
}
}]);
factory 可以有自己的依赖,像上面的代码,factory 可以 注入 $window 服务来调用 win.alert("")。而且service 就不行了。
或者 :
app.factory('helloWorld', ['$rootScope','$http',function($rootScope, $http) {
}]);
--源码
为了理解根本上的不同,可以扒一下源码来看看两个func的实现:
function provider(name, provider_) {
if (isFunction(provider_) || isArray(provider_)) { //判断是函数还是数组
provider_ = providerInjector.instantiate(provider_);
}
if (!provider_.$get) {
throw Error('Provider ' + name + ' must define $get factory method.');
}
return providerCache[name + providerSuffix] = provider_;
}
function factory(name, factoryFn) {
return provider(name, { $get: factoryFn });
}
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
--factory研究
可以看到 factory 是对 provider的封装, 举个例子:
var app = angular.module('myApp',[],function($provide) {
$provide.provider('age',{
start : 10 ,
$get : function() {
return this.start + 10 ;
}
});
});
or : 添加注入器案例:
var app = angular.module('myApp',[],function($provide) {
$provide.provider('age',{
start : 10 ,
$get : ['$window',function(win) {
win.alert('hi');
return this.start + 10 ;
}]
});
});
function HelloCtrl($scope,age){
$scope.myage = age;
}
provider 是通过 $get 来在应用中注入单例,使用时取到的age就是 $get 返回的结果 。
结论就是:factory 是封装且简化了provide的一个功能,返回对象 。
--service研究
从源码看,service 就是小三, 是对 factory 进行 更上一层的封装。
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
总结 : service 就是 调用了 $injector 注入器的 factory ,简化数据共享的实现!
最后
service 和 factory 都是单例模式(单例模式是一种设计模式)
看案例代码:
app.service('Service', function(){
this.name = 'yeelone';
this.set = function(name){
this.name = name ;
};
this.get = function(){
return this.name;
};
});
function HelloCtrl($scope,Service){
$scope.name = Service.get();
Service.set('newName');
}
function ByeCtrl($scope,Service){
$scope.name = Service.get();
}
输出结果 :
yeelone
newName
var app = angular.module('myApp',[]);
app.factory('NameFactory',function(){
var name = 'init';
return {
set : function(name){
this.name = name ;
},
get : function(){
return this.name ;
}
};
}
);
function HelloCtrl($scope,NameFactory){
NameFactory.set('yeelone');
$scope.name = NameFactory.get();
}
function ByeCtrl($scope,NameFactory){
$scope.name2 = NameFactory.get();
}
service和factory可以 实现 controller 之间的数据共享!