Keywords: AngularJS | Service | Factory | Singleton Pattern | Dependency Injection
Abstract: This article provides an in-depth exploration of the core distinctions and common characteristics between Service and Factory in AngularJS. By analyzing official documentation and code examples, it reveals the singleton nature of both, detailing how Service instantiates via constructor while Factory creates through returned objects. The text illustrates state sharing mechanisms in controller injection scenarios and includes extended discussions on Provider patterns as supplementary reference.
Overview of AngularJS Service Injection Mechanism
In the AngularJS framework, the dependency injection system is designed following the singleton pattern principle. As explicitly stated in the official documentation: All Angular services are application singletons. This means that within each injector's scope, a specific service exists as a single instance only. This characteristic ensures data state sharing and consistency across multiple controllers.
Core Differences Between Service and Factory
The primary distinction between Service and Factory lies in their instantiation methods:
- Service is invoked as a constructor function using the
newkeyword. In Service definitions, properties and methods are added via thethiskeyword, with no explicit object return required. - Factory returns an object through function execution. Developers can execute initialization code before returning the object, which becomes the injected instance.
The following code example clearly demonstrates the syntactic differences between the two definition approaches:
app.service('myService', function() {
this.sayHello = function(name) {
return "Hi " + name + "!";
};
});
app.factory('myFactory', function() {
return {
sayHello: function(name) {
return "Hi " + name + "!";
}
};
});Singleton Pattern Verification and Controller Injection
The singleton behavior can be verified through the user-provided example code:
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;
});When modifying the user.first property in ACtrl, the user.first in BCtrl also changes, confirming that the User factory is indeed a singleton instance, with multiple controllers sharing the same object reference.
Underlying Implementation Mechanism Analysis
AngularJS internally maintains a cache object to store singleton instances of all registered services:
- For
factory, the cached value is the function execution result:cache.a = fn() - For
service, the cached value is the constructor instantiation result:cache.b = new fn() - For
provider, the cached value is obtained through the instance's$getmethod:cache.c = (new fn()).$get()
This design ensures that regardless of how a service is defined, only a single instance exists per injector, guaranteeing state consistency and optimizing performance.
Practical Application Recommendations
When choosing between Service and Factory, consider the following factors:
- Factory provides more flexible initialization processes for simple object encapsulation
- Service's constructor form better aligns with traditional object-oriented patterns
- No significant performance differences exist between the two; selection should be based on coding style and specific requirements
Understanding this core mechanism helps developers better design AngularJS application architecture, avoiding unnecessary instance creation while ensuring data flow consistency.