AngularJS: Cuándo usar el servicio en lugar de la fábrica

Por favor, tengan paciencia aquí. Sé que hay otras respuestas como: AngularJS: Servicio vs proveedor vs fábrica

Sin embargo, todavía no puedo entender cuándo utilizarías el servicio en lugar de la fábrica.

De lo que puedo decir, la fábrica se usa comúnmente para crear funciones “comunes” que pueden ser llamadas por múltiples Controladores: Creación de funciones de controlador comunes

Los documentos angulares parecen preferir la fábrica al servicio. ¡Incluso se refieren al “servicio” cuando usan fábrica, lo que es aún más confuso! http://docs.angularjs.org/guide/dev_guide.services.creating_services

Entonces, ¿cuándo usaría uno el servicio?

¿Hay algo que solo sea posible o mucho más fácil de hacer con el servicio?

¿Hay algo diferente que ocurra detrás de escena? ¿Diferencias de rendimiento / memoria?

Aquí hay un ejemplo. Aparte del método de statement, parecen idénticos y no puedo entender por qué haría uno frente al otro. http://jsfiddle.net/uEpkE/

Actualización: A partir de la respuesta de Thomas, parece implicar que el servicio es para una lógica más simple y de fábrica para una lógica más compleja con métodos privados, así que actualicé el código de violín a continuación y parece que ambos pueden admitir funciones privadas.

myApp.factory('fooFactory', function() { var fooVar; var addHi = function(foo){ fooVar = 'Hi '+foo; } return { setFoobar: function(foo){ addHi(foo); }, getFoobar:function(){ return fooVar; } }; }); myApp.service('fooService', function() { var fooVar; var addHi = function(foo){ fooVar = 'Hi '+foo;} this.setFoobar = function(foo){ addHi(foo); } this.getFoobar = function(){ return fooVar; } }); function MyCtrl($scope, fooService, fooFactory) { fooFactory.setFoobar("fooFactory"); fooService.setFoobar("fooService"); //foobars = "Hi fooFactory, Hi fooService" $scope.foobars = [ fooFactory.getFoobar(), fooService.getFoobar() ]; } 

    Explicación

    Tienes cosas diferentes aquí:

    Primero:

    • Si usa un servicio, obtendrá la instancia de una función (” this ” palabra clave).
    • Si usa una fábrica obtendrá el valor que se devuelve al invocar la referencia de función (la statement de devolución en fábrica).

    ref: angular.service versus angular.factory

    Segundo:

    ¡Tenga en cuenta que todos los proveedores en AngularJS (valor, constante, servicios, fábricas) son únicos!

    Tercero:

    Usar uno u otro (servicio o fábrica) tiene que ver con el estilo del código. Pero, la forma común en AngularJS es usar fábrica .

    Por qué ?

    Porque “El método de fábrica es la forma más común de introducir objetos en el sistema de dependency injections 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 scope léxico para simular” privadas “variables. Esto es muy útil ya que podemos ocultar los detalles de implementación de un servicio determinado”.

    ( ref : http://www.amazon.com/Mastering-Web-Application-Development-AngularJS/dp/1782161821 ).


    Uso

    Servicio: podría ser útil para compartir funciones de utilidad que son útiles para invocar simplemente agregando () a la referencia de función inyectada. También se podría ejecutar con injectedArg.call(this) o similar.

    Fábrica: podría ser útil para devolver una función de ‘clase’ que luego puede ser `nueva ‘para crear instancias.

    Entonces, use una fábrica cuando tenga una lógica compleja en su servicio y no quiera exponer esta complejidad .

    En otros casos, si desea devolver una instancia de un servicio simplemente use el servicio .

    Pero verás con el tiempo que utilizarás la fábrica en el 80% de los casos, creo.

    Para más detalles: http://blog.manishchhabra.com/2013/09/angularjs-service-vs-factory-with-example/


    ACTUALIZAR:

    Excelente publicación aquí: http://iffycan.blogspot.com.ar/2013/05/angular-service-or-factory.html

    “Si quiere que su función se llame como una función normal , use Factory . Si desea que su función sea instanciada con el nuevo operador, use el servicio. Si no conoce la diferencia, use Factory”.


    ACTUALIZAR:

    El equipo de AngularJS hace su trabajo y da una explicación: http://docs.angularjs.org/guide/providers

    Y desde esta página:

    “La fábrica y el servicio son las recetas más utilizadas. La única diferencia entre ellas es que la receta de servicio funciona mejor para los objetos de tipo personalizado, mientras que Factory puede producir primitivas y funciones de JavaScript”.

    allernhwkim originalmente publicó una respuesta sobre esta cuestión vinculando a su blog , sin embargo, un moderador lo eliminó. Es la única publicación que he encontrado que no solo te dice cómo hacer lo mismo con el servicio, el proveedor y la fábrica, sino que también te dice qué puedes hacer con un proveedor que no puedes con una fábrica, y con una fábrica que no se puede con un servicio.

    Directamente desde su blog:

     app.service('CarService', function() { this.dealer="Bad"; this.numCylinder = 4; }); app.factory('CarFactory', function() { return function(numCylinder) { this.dealer="Bad"; this.numCylinder = numCylinder }; }); app.provider('CarProvider', function() { this.dealerName = 'Bad'; this.$get = function() { return function(numCylinder) { this.numCylinder = numCylinder; this.dealer = this.dealerName; } }; this.setDealerName = function(str) { this.dealerName = str; } }); 

    Esto muestra cómo el CarService siempre producirá un automóvil con 4 cilindros, no puede cambiarlo para automóviles individuales. Mientras que CarFactory devuelve una función para que pueda hacer new CarFactory en su controlador, pasando una serie de cilindros específicos para ese automóvil. No puede hacer new CarService porque CarService es un objeto, no una función.

    Las fábricas de motivos no funcionan así:

     app.factory('CarFactory', function(numCylinder) { this.dealer="Bad"; this.numCylinder = numCylinder }); 

    Y devuelve automáticamente una función para que usted cree una instancia, es porque entonces no puede hacer esto (agregue cosas al prototipo / etc):

     app.factory('CarFactory', function() { function Car(numCylinder) { this.dealer="Bad"; this.numCylinder = numCylinder }; Car.prototype.breakCylinder = function() { this.numCylinder -= 1; }; return Car; }); 

    Vea cómo es literalmente una fábrica que produce un automóvil.

    La conclusión de su blog es bastante buena:

    En conclusión,

     --------------------------------------------------- | Provider| Singleton| Instantiable | Configurable| --------------------------------------------------- | Factory | Yes | Yes | No | --------------------------------------------------- | Service | Yes | No | No | --------------------------------------------------- | Provider| Yes | Yes | Yes | --------------------------------------------------- 
    1. Use el servicio cuando solo necesite un objeto simple como Hash, por ejemplo {foo; 1, bar: 2}. Es fácil de codificar, pero no puede crear una instancia.

    2. Use Factory cuando necesite instanciar un objeto, es decir, nuevo Cliente (), nuevo Comentario (), etc.

    3. Use el proveedor cuando necesite configurarlo. es decir, URL de prueba, QA url, url de producción.

    Si descubre que está devolviendo un objeto en la fábrica probablemente debería usar el servicio.

    No hagas esto:

     app.factory('CarFactory', function() { return { numCylinder: 4 }; }); 

    Use el servicio en su lugar:

     app.service('CarService', function() { this.numCylinder = 4; }); 

    El concepto para todos estos proveedores es mucho más simple de lo que parece inicialmente. Si disecciona un proveedor y saca las diferentes partes, queda muy claro.

    En pocas palabras, cada uno de estos proveedores es una versión especializada del otro, en este orden: provider > factory > value / constant / service .

    Mientras el proveedor haga lo que pueda, puede utilizar el proveedor más adelante en la cadena, lo que daría como resultado escribir menos código. Si no logra lo que desea, puede subir la cadena y tendrá que escribir más código.

    Esta imagen ilustra lo que quiero decir, en esta imagen verá el código de un proveedor, con las partes resaltadas que le muestran qué partes del proveedor se pueden usar para crear una fábrica, valor, etc. en su lugar.

    Los proveedores, las fábricas, los servicios, etc. de AngularJS son lo mismo http://sofes.miximages.com/angularjs/angularjs-provider-service-factory-highlight.png

    Para obtener más detalles y ejemplos de la publicación del blog donde obtuve la imagen, vaya a: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

    Tanto la fábrica como el servicio dan como resultado objetos únicos que pueden ser configurados por los proveedores e inyectados en controladores y ejecutar bloques. Desde el punto de vista del inyectado, no hay absolutamente ninguna diferencia si el objeto proviene de una fábrica o un servicio.

    Entonces, ¿cuándo usar una fábrica y cuándo usar un servicio? Se reduce a su preferencia de encoding, y nada más. Si te gusta el patrón modular JS, ve a la fábrica. Si te gusta el estilo de la función de constructor (“clase”), elige el servicio. Tenga en cuenta que ambos estilos admiten miembros privados.

    La ventaja del servicio podría ser que es más intuitivo desde el punto de vista de OOP: cree una “clase” y, junto con un proveedor, reutilice el mismo código entre los módulos y modifique el comportamiento de los objetos instanciados simplemente mediante el suministro. diferentes parámetros para el constructor en un bloque de configuración.

    No hay nada que una fábrica no pueda hacer o haga mejor en comparación con un servicio. Y viceversa. La fábrica parece ser más popular. La razón de esto es su conveniencia en el manejo de miembros privados / públicos. El servicio sería más torpe en este sentido. Al codificar un servicio, tiende a hacer que los miembros de su objeto sean públicos mediante la palabra clave “this” y de repente puede descubrir que esos miembros públicos no son visibles para métodos privados (es decir, funciones internas).

     var Service = function(){ //public this.age = 13; //private function getAge(){ return this.age; //private does not see public } console.log("age: " + getAge()); }; var s = new Service(); //prints 'age: undefined' 

    Angular usa la palabra clave “nueva” para crear un servicio para usted, por lo que la instancia que Angular pasa al controlador tendrá el mismo inconveniente. Por supuesto, puede superar el problema usando this / that:

     var Service = function(){ var that = this; //public this.age = 13; //private function getAge(){ return that.age; } console.log("age: " + getAge()); }; var s = new Service();// prints 'age: 13' 

    Pero con una constante de servicio grande, esto haría que el código sea poco legible. Además, los prototipos del Servicio no verán miembros privados, solo el público estará disponible para ellos:

     var Service = function(){ var name = "George"; }; Service.prototype.getName = function(){ return this.name; //will not see a private member }; var s = new Service(); console.log("name: " + s.getName());//prints 'name: undefined' 

    En resumen, usar Factory es más conveniente. Como Factory no tiene estos inconvenientes. Yo recomendaría usarlo por defecto.

    Incluso cuando dicen que todos los servicios y fábricas son únicos, no estoy de acuerdo al 100 por ciento con eso. Yo diría que las fábricas no son simples y este es el punto de mi respuesta. Realmente pensaría en el nombre que define cada componente (Servicio / Fábrica), quiero decir:

    Una fábrica porque no es un singleton, puede crear tantos como desee cuando se inyecta, por lo que funciona como una fábrica de objetos. Puede crear una fábrica de una entidad de su dominio y trabajar más cómodamente con estos objetos que podrían ser como un objeto de su modelo. Cuando recupera varios objetos, puede mapearlos en estos objetos y puede actuar como una capa más entre el DDBB y el modelo AngularJs. Puede agregar métodos a los objetos para orientarlos un poco más a su aplicación AngularJs.

    Mientras tanto, un servicio es singleton, por lo que solo podemos crear 1 de un tipo, quizás no crear, pero solo tenemos 1 instancia cuando inyectamos en un controlador, por lo que un servicio ofrece más como un servicio común (llamadas de descanso, funcionalidad …) a los controladores.

    Conceptualmente, usted puede pensar que los servicios brindan un servicio, las fábricas pueden crear instancias múltiples (objetos) de una clase

    Servicios

    Sintaxis : module.service (‘serviceName’, function); Resultado : cuando declare serviceName como un argumento inyectable, se le proporcionará la referencia de función real pasada a module.service.

    Uso : podría ser útil para compartir funciones de utilidad que son útiles para invocar simplemente agregando () a la referencia de función inyectada. También se podría ejecutar con injectedArg.call (this) o similar.

    Suerte

    Sintaxis : module.factory (‘factoryName’, function);

    Resultado : al declarar factoryName como un argumento inyectable, se le proporcionará el valor que se devuelve al invocar la referencia de función pasada a module.factory.

    Uso : podría ser útil para devolver una función de ‘clase’ que luego se puede renovar para crear instancias.

    Proveedores

    Sintaxis : module.provider (‘providerName’, function);

    Resultado : al declarar providerName como un argumento inyectable, se le proporcionará el valor que se devuelve al invocar el método $ get de la referencia de función pasada a module.provider.

    Uso : podría ser útil para devolver una función de ‘clase’ que luego puede ser renovada para crear instancias, pero eso requiere algún tipo de configuración antes de ser inyectado. ¿Quizás útil para clases que son reutilizables en todos los proyectos? Todavía un poco confuso en este caso.

    Puede usar las dos formas que desee : si crea un objeto o j ust para acceder a las funciones de ambos


    Puede crear un objeto nuevo desde el servicio

     app.service('carservice', function() { this.model = function(){ this.name = Math.random(22222); this.price = 1000; this.colour = 'green'; this.manufacturer = 'bmw'; } }); .controller('carcontroller', function ($scope,carservice) { $scope = new carservice.model(); }) 

    Nota :

    • el servicio devuelve por defecto el objeto y no la función constructora.
    • Entonces esa es la razón por la cual la función constructor está configurada en la propiedad this.model.
    • Debido a este servicio devolverá el objeto, pero pero dentro de ese objeto habrá una función de constructor que se usará para crear un nuevo objeto;

    Puede crear un nuevo objeto de fábrica

     app.factory('carfactory', function() { var model = function(){ this.name = Math.random(22222); this.price = 1000; this.colour = 'green'; this.manufacturer = 'bmw'; } return model; }); .controller('carcontroller', function ($scope,carfactory) { $scope = new carfactory(); }) 

    Nota :

    • fábrica de forma predeterminada devuelve la función constructora y no el objeto.
    • Entonces, es por eso que se puede crear un nuevo objeto con la función de constructor.

    Crear servicio para acceder a funciones simples

     app.service('carservice', function () { this.createCar = function () { console.log('createCar'); }; this.deleteCar = function () { console.log('deleteCar'); }; }); .controller('MyService', function ($scope,carservice) { carservice.createCar() }) 

    Crear fábrica solo para acceder a funciones simples

     app.factory('carfactory', function () { var obj = {} obj.createCar = function () { console.log('createCar'); }; obj.deleteCar = function () { console.log('deleteCar'); }; }); .controller('MyService', function ($scope,carfactory) { carfactory.createCar() }) 

    Conclusión

    • puede usar tanto como desee si crea un objeto nuevo o simplemente para acceder a funciones simples
    • No habrá ningún golpe de rendimiento, usando uno sobre el otro
    • Ambos son objetos únicos y solo se crea una instancia por aplicación.
    • Siendo solo una instancia cada vez que se pasa su referencia.
    • En la documentación angular, la fábrica se llama servicio y también el servicio se llama servicio .