Questo è ciò che mi ha aiutato a capire la differenza, grazie a un post sul blog di Pascal Precht.
Un servizio è un metodo su un modulo che accetta un nome e una funzione che definisce il servizio. È possibile iniettare e utilizzare quel particolare servizio in altri componenti, come controller, direttive e filtri. Una factory è un metodo su un modulo e richiede anche un nome e una funzione, che definisce la factory. Possiamo anche iniettare e utilizzare come abbiamo fatto con il servizio.
Gli oggetti creati con nuovo usano il valore della proprietà prototipo della loro funzione di costruzione come prototipo, quindi ho trovato il codice angolare che chiama Object.create (), che credo sia la funzione di costruzione del servizio quando viene istanziata. Tuttavia, una funzione factory è in realtà solo una funzione che viene chiamata, motivo per cui dobbiamo restituire un oggetto letterale per la factory.
Ecco il codice 1.5 angolare che ho trovato per la fabbrica:
var needsRecurse = false;
var destination = copyType(source);
if (destination === undefined) {
destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
needsRecurse = true;
}
Frammento di codice sorgente angolare per la funzione factory ():
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
Prende il nome e la funzione factory che viene passata e restituisce un provider con lo stesso nome, che ha un metodo $ get che è la nostra funzione factory. Ogni volta che chiedi all'iniettore una dipendenza specifica, in pratica chiede al provider corrispondente un'istanza di quel servizio, chiamando il metodo $ get (). Ecco perché $ get () è richiesto, durante la creazione di provider.
Ecco il codice angolare 1.5 per l'assistenza.
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
Si scopre che quando chiamiamo service (), in realtà chiama factory ()! Tuttavia, non solo passa la nostra funzione di costruttore di servizi alla fabbrica così com'è. Passa anche una funzione che chiede all'iniettore di creare un'istanza di un oggetto dal costruttore dato.
In altre parole, se iniettiamo MyService da qualche parte, ciò che accade nel codice è:
MyServiceProvider.$get(); // return the instance of the service
Per riaffermarlo di nuovo, un servizio chiama una factory, che è un metodo $ get () sul provider corrispondente. Inoltre, $ injector.instantiate () è il metodo che alla fine chiama Object.create () con la funzione di costruzione. Ecco perché usiamo "questo" nei servizi.
Per ES5 non importa quale utilizziamo: service () o factory (), è sempre una factory chiamata che crea un provider per il nostro servizio.
Puoi fare esattamente la stessa cosa anche con i servizi. Un servizio è una funzione di costruzione, tuttavia, che non ci impedisce di restituire valori letterali di oggetti. Quindi possiamo prendere il nostro codice di servizio e scriverlo in modo che sostanzialmente faccia la stessa cosa della nostra fabbrica o in altre parole, puoi scrivere un servizio come fabbrica per restituire un oggetto.
Perché la maggior parte delle persone consiglia di utilizzare le fabbriche rispetto ai servizi? Questa è la migliore risposta che ho visto che proviene dal libro di Pawel Kozlowski: padroneggiare lo sviluppo di applicazioni Web con AngularJS.
Il metodo di fabbrica è il modo più comune per ottenere oggetti nel sistema di iniezione di dipendenza AngularJS. È molto flessibile e può contenere una sofisticata logica di creazione. Poiché le fabbriche sono funzioni regolari, possiamo anche trarre vantaggio da un nuovo ambito lessicale per simulare variabili "private". Questo è molto utile in quanto possiamo nascondere i dettagli di implementazione di un determinato servizio. "