Foi isso que me ajudou a entender a diferença, graças a um post de Pascal Precht.
Um serviço é um método em um módulo que leva um nome e uma função que define o serviço. Você pode injetar e usar esse serviço específico em outros componentes, como controladores, diretivas e filtros. Uma fábrica é um método em um módulo e também leva um nome e uma função, que define a fábrica. Também podemos injetar e usar da mesma maneira que fizemos com o serviço.
Os objetos criados com o novo usam o valor da propriedade prototype de sua função construtora como protótipo; portanto, encontrei o código Angular que chama Object.create (), que acredito ser a função construtora de serviço quando é instanciada. No entanto, uma função de fábrica é realmente apenas uma função que é chamada, e é por isso que precisamos retornar um objeto literal para a fábrica.
Aqui está o código angular 1.5 que encontrei para a 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-fonte angular para a função factory ():
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
Ele pega o nome e a função de fábrica que é passada e retorna um provedor com o mesmo nome, que possui um método $ get, que é a nossa função de fábrica. Sempre que você solicita ao injetor uma dependência específica, ele basicamente solicita ao provedor correspondente uma instância desse serviço, chamando o método $ get (). É por isso que $ get () é necessário ao criar provedores.
Aqui está o código angular 1.5 para serviço.
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
Acontece que quando chamamos service (), na verdade, chama factory ()! No entanto, ele não apenas passa nossa função de construtor de serviço para a fábrica como está. Ele também passa uma função que solicita ao injetor que instancia um objeto pelo construtor especificado.
Em outras palavras, se injetarmos o MyService em algum lugar, o que acontece no código é:
MyServiceProvider.$get(); // return the instance of the service
Para reajustá-lo novamente, um serviço chama uma fábrica, que é um método $ get () no provedor correspondente. Além disso, $ injector.instantiate () é o método que finalmente chama Object.create () com a função construtora. É por isso que usamos "isso" nos serviços.
Para o ES5, não importa qual seja o uso: service () ou factory (), é sempre uma fábrica chamada que cria um provedor para o nosso serviço.
Você pode fazer exatamente a mesma coisa com os serviços também. Um serviço é uma função construtora, no entanto, que não nos impede de retornar literais de objetos. Assim, podemos pegar nosso código de serviço e escrevê-lo de uma maneira que basicamente faz exatamente a mesma coisa que nossa fábrica ou, em outras palavras, você pode escrever um serviço como fábrica para retornar um objeto.
Por que a maioria das pessoas recomenda usar fábricas em vez de serviços? Esta é a melhor resposta que eu vi que vem do livro de Pawel Kozlowski: Mastering Web Application Development with AngularJS.
O método de fábrica é a maneira mais comum de colocar objetos no sistema de injeção de dependência do AngularJS. É muito flexível e pode conter lógica de criação sofisticada. Como as fábricas são funções regulares, também podemos tirar proveito de um novo escopo lexical para simular variáveis "privadas". Isso é muito útil, pois podemos ocultar os detalhes da implementação de um determinado serviço ".