Esto es lo que me ayudó a entender la diferencia, gracias a una publicación de blog de Pascal Precht.
Un servicio es un método en un módulo que toma un nombre y una función que define el servicio. Puede inyectar y usar ese servicio en particular en otros componentes, como controladores, directivas y filtros. Una fábrica es un método en un módulo y también toma un nombre y una función que define la fábrica. También podemos inyectar y usarlo de la misma manera que lo hicimos con el servicio.
Los objetos creados con nuevo usan el valor de la propiedad prototipo de su función de constructor como su prototipo, por lo que encontré el código angular que llama a Object.create (), que creo que es la función de constructor de servicios cuando se instancia. Sin embargo, una función de fábrica es realmente solo una función que se llama, por lo que tenemos que devolver un objeto literal para la fábrica.
Aquí está el código angular 1.5 que encontré para la fábrica:
var needsRecurse = false;
var destination = copyType(source);
if (destination === undefined) {
destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
needsRecurse = true;
}
Fragmento de código fuente angular para la función factory ():
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
Toma el nombre y la función de fábrica que se pasa y devuelve un proveedor con el mismo nombre, que tiene un método $ get que es nuestra función de fábrica. Cada vez que le pide al inyector una dependencia específica, básicamente le pide al proveedor correspondiente una instancia de ese servicio, llamando al método $ get (). Es por eso que se requiere $ get () al crear proveedores.
Aquí está el código angular 1.5 para servicio.
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
¡Resulta que cuando llamamos al servicio (), en realidad llama a la fábrica ()! Sin embargo, no solo pasa nuestra función de constructor de servicios a la fábrica tal como está. También pasa una función que le pide al inyector que cree una instancia de un objeto por el constructor dado.
En otras palabras, si inyectamos MyService en algún lugar, lo que sucede en el código es:
MyServiceProvider.$get(); // return the instance of the service
Para volver a expresarlo, un servicio llama a una fábrica, que es un método $ get () en el proveedor correspondiente. Además, $ injector.instantiate () es el método que finalmente llama a Object.create () con la función de constructor. Es por eso que usamos "esto" en los servicios.
Para ES5, no importa cuál usemos: service () o factory (), siempre se llama una fábrica que crea un proveedor para nuestro servicio.
Sin embargo, también puede hacer exactamente lo mismo con los servicios. Sin embargo, un servicio es una función constructora que no nos impide devolver literales de objeto. Por lo tanto, podemos tomar nuestro código de servicio y escribirlo de una manera que básicamente haga exactamente lo mismo que nuestra fábrica o, en otras palabras, puede escribir un servicio como fábrica para devolver un objeto.
¿Por qué la mayoría de la gente recomienda usar fábricas en lugar de servicios? Esta es la mejor respuesta que he visto que proviene del libro de Pawel Kozlowski: Dominar el desarrollo de aplicaciones web con AngularJS.
El método de fábrica es la forma más común de introducir objetos en el sistema de inyección de dependencia AngularJS. Es muy flexible y puede contener una lógica de creación sofisticada. Como las fábricas son funciones regulares, también podemos aprovechar un nuevo ámbito léxico para simular variables "privadas". Esto es muy útil ya que podemos ocultar los detalles de implementación de un servicio determinado ".