Serviços vs. Fábricas em Angular

EDIT 2016. Note que este post, que é um repost de um post a partir de 2015, é sobre Angular 1. Eu não faço mais frontend então não há garantias de que este post seja relevante para o Angular 2 ;).

Um dos meus colegas de classe do Hack Reactor e eu recentemente construí uma calculadora de tratamento de pressão alta para a Moxe Health, uma empolgante empresa Rock Health que está construindo um sistema de integração de banco de dados e API que permitirá a qualquer desenvolvedor acessar os registros médicos eletrônicos de qualquer hospital na rede da Moxe. Estou empolgado em falar sobre o Moxe e o projeto em outro post. Nós construímos o front-end do aplicativo em Angular, um poderoso front-end framework com encadernação de dados e outros recursos incríveis. Uma coisa que foi confusa foi quando usar serviços vs. fábricas. Stack Overflow tem um bom tópico sobre a diferença entre os dois, mas deixa de fora algumas analogias que eu acho que são úteis para desenvolvedores ainda cimentarem seus conhecimentos de Javascript.

Neste post, você vai aprender a diferença entre os dois.

TLDR – fábricas e serviços têm praticamente a mesma funcionalidade em termos de sua capacidade de instanciar e enscapsular métodos e propriedades, muito parecido com instanciação funcional e padrões pseudoclássicos de instanciação têm habilidades similares. Não há preferência na comunidade Angular pelo uso de um ou outro. As receitas de fábrica e de serviço são apenas açúcar sintáctico em cima da receita do fornecedor. Então a pergunta que você deveria estar fazendo a si mesmo normalmente não é “eu deveria estar usando fábricas ou serviços?” mas sim “eu deveria estar usando instanciação funcional ou instanciação pseudoclássica?”

Afora esse entendimento de alto nível, a diferença mais significativa é que, como resultado da diferença em seus padrões de instanciação, as fábricas podem retornar primitivas e funções, mas os serviços não podem.

Primitivas, funções e objetos, oh meu!

Cheque este JSFiddle. Crédito ao Epokk por fornecer a maior parte do código. Eu fiz algumas modificações que, mais uma vez, realmente ajudam os desenvolvedores novos para a Angular a perfurar a diferença aqui. Se você é novo no JSFiddle, é uma ferramenta que lhe permite testar facilmente as interações entre seus arquivos javascript, html e css. Assim você pode brincar com o código, e ele não vai sobrescrever o código original no link.

Bambos o serviço e a fábrica neste exemplo têm a mesma funcionalidade de retornar a string “Hello World! A diferença é como eles fazem.

O serviço instancia um objeto e atribui a função que retorna “Hello World!” para a propriedade “sayHello” desse objeto:

this.sayHello = function() { return "Hello, World!" };

O método é então invocado no controller: helloWorldFromService.sayHello().

A fábrica retorna uma função que retorna “Hello World!”:

return function() { return "Hello, World!" };

A função é então invocada no controller: helloWorldFromFactory(). Note como a referência da fábrica aponta para a função retornada, ao invés da propriedade de um objeto cujo valor é uma função, como no exemplo de serviço. Um serviço nunca poderia fazer isso, pois um serviço deve instanciar um objeto vazio cuja referência dentro do corpo da função de serviço é ‘isto’. Os serviços sempre retornam objetos.

Aqui está a parte das fábricas que pode ser confusa. A fábrica também pode retornar um objeto que tem um método ‘sayHello’, muito parecido com o service:

return { sayHello: function() { return "Hello, World!" } };

Que você invocaria no controller exatamente como invocaria a função sayHello do serviço: helloWorldFromFactory.sayHello().

O último formato de fábrica é útil quando você quer ter múltiplos métodos em uma fábrica:

return { sayHello: function() { return "Hello, World!" }, sayGoodbye: function() { return "Goodbye, World!" } };

Again, a chave aqui não é ficar preso no fato de que você está codificando em Angular, e lembrando que as diferenças entre serviços e fábricas são na maioria das vezes as mesmas que as diferenças entre a instanciação pseudoclássica e a instanciação funcional.

Código fonte para os curiosos

Aqui está o código fonte Angular, demonstrando que os serviços &fábricas estão em camadas em cima da característica mais geral dos provedores:

//provider function provider(name, provider_) { assertNotHasOwnProperty(name, 'service'); if (isFunction(provider_) || isArray(provider_)) { provider_ = providerInjector.instantiate(provider_); } if (!provider_.$get) { throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); } return providerCache = provider_; } //factory function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } //service function service(name, constructor) { return factory(name, ); }

Bambos serviços e fábricas criam singletons. Padrões básicos funcionais vs. herança pseudoclássica aqui. A fábrica retorna o que quer que o factoryFn retorne.

O serviço retorna uma instância de uma pseudo-classe. O construtor da pseudo-classe é passado para o service builder service() da Angular. O fato do construtor ser passado para o service builder service (retorna $injector.instantiate(construtor)) pode ser confuso, mas pense nisso como retorna novo construtor().

Codificação Feliz!

Leave a Reply