AngularJS: Wann Service statt Fabrik zu verwenden

Bitte ertragen Sie mich hier. Ich weiß, es gibt andere Antworten wie: AngularJS: Service vs Provider vs Fabrik

Ich kann jedoch immer noch nicht herausfinden, wann Sie den Service über die Fabrik nutzen würden.

Von dem, was ich sagen kann, wird factory üblicherweise verwendet, um “allgemeine” functionen zu erstellen, die von mehreren Controllern aufgerufen werden können: Gemeinsame Controller-functionen erstellen

Die Angular Docs scheinen Fabrik gegenüber Service vorzuziehen. Sie beziehen sich sogar auf “Service”, wenn sie Fabrik verwenden, die noch verwirrender ist! http://docs.angularjs.org/guide/dev_guide.services.creating_services

Wann sollte man Service nutzen?

Gibt es etwas, das nur mit Service möglich oder viel einfacher ist?

Gibt es etwas anderes, das sich hinter den Kulissen abspielt? Performance / Speicher Unterschiede?

Hier ist ein Beispiel. Anders als die Methode der Erklärung scheinen sie identisch zu sein und ich kann nicht herausfinden, warum ich eine gegen die andere machen würde. http://jsfiddle.net/uEpkE/

Update: Von Thomas ‘Antwort scheint es zu bedeuten, dass der Dienst für einfachere Logik und Fabrik für komplexere Logik mit privaten Methoden ist, also habe ich den untenstehenden Geigencode aktualisiert und es scheint, dass beide in der Lage sind, private functionen zu unterstützen?

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() ]; } 

    Erläuterung

    Du hast verschiedene Dinge hier:

    Zuerst:

    • Wenn Sie einen Dienst verwenden, erhalten Sie die Instanz einer function (” this ” Schlüsselwort).
    • Wenn Sie eine Factory verwenden, erhalten Sie den Wert, der durch Aufrufen der functionsreferenz zurückgegeben wird (die Rückgabebestätigung im Werk).

    ref: angular.service gegen angular.factory

    Zweite:

    Bedenken Sie, dass alle Anbieter in AngularJS (Value, Constant, Services, Factories) Singletons sind!

    Dritte:

    Das Verwenden des einen oder des anderen (Service oder Fabrik) ist über den Codestil. Aber der übliche Weg in AngularJS ist die Verwendung von Factory .

    Warum ?

    Weil “die Fabrikmethode die gebräuchlichste Methode ist, um Objekte in das AngularJS Abhängigkeitsinjektionssystem zu bekommen. Es ist sehr flexibel und kann ausgeklügelte Erstellungslogik enthalten. Da Fabriken reguläre functionen sind, können wir auch einen neuen lexikalischen Bereich nutzen, um” private “zu simulieren “Variablen. Dies ist sehr nützlich, da wir Implementierungsdetails eines bestimmten Dienstes verbergen können.”

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


    Verwendung

    Dienst: Kann hilfreich sein, um nützliche Dienstprogrammfunktionen zu teilen, indem Sie einfach () an die Referenz der injizierten function anhängen. Könnte auch mit injectedArg.call(this) oder ähnlichem ausgeführt werden.

    Factory: Kann nützlich sein, um eine ‘classn’-function zurückzugeben, die dann zum Erstellen von Instanzen neu erstellt werden kann.

    Verwenden Sie also eine Factory, wenn Sie komplexe Logik in Ihrem Service haben und diese Komplexität nicht offen legen wollen .

    In anderen Fällen, wenn Sie eine Instanz eines Dienstes zurückgeben möchten, verwenden Sie einfach den Dienst .

    Aber Sie werden mit der Zeit sehen, dass Sie Fabrik in 80% der Fälle verwenden werden, denke ich.

    Für weitere Details: http://blog.manishchhabra.com/2013/09/angularjs-service-vs-factory-with-example/


    UPDATE:

    Ausgezeichneter Beitrag hier: http://iffycan.blogspot.com.ar/2013/05/angular-service-or-factory.html

    “Wenn Sie möchten, dass Ihre function wie eine normale function aufgerufen wird , verwenden Sie Factory . Wenn Sie möchten, dass Ihre function mit dem neuen Operator instanziiert wird, verwenden Sie den Service. Wenn Sie den Unterschied nicht kennen, verwenden Sie die Factory.”


    UPDATE:

    AngularJS Team macht seine Arbeit und gibt eine Erklärung: http://docs.angularjs.org/guide/providers

    Und von dieser Seite:

    “Factory und Service sind die am häufigsten verwendeten Rezepte. Der einzige Unterschied zwischen ihnen besteht darin, dass das Service-Rezept für Objekte des benutzerdefinierten Typs besser funktioniert, während Factory JavaScript-Primitive und -functionen erzeugen kann.”

    Allerhnhwkim hat ursprünglich eine Antwort auf diese Frage gepostet, die zu seinem Blog verlinkt, aber ein Moderator hat es gelöscht. Es ist der einzige Beitrag, den ich gefunden habe, der Ihnen nicht nur sagt, wie Sie das Gleiche mit Service, Provider und Fabrik tun, sondern auch, was Sie mit einem Provider machen können, den Sie nicht mit einer Factory und mit eine Fabrik, die Sie nicht mit einem Service erreichen können.

    Direkt von seinem 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; } }); 

    Dies zeigt, wie der CarService immer ein Auto mit 4 Zylindern produzieren wird, Sie können es nicht für einzelne Autos ändern. Während CarFactory eine function zurückgibt, können Sie new CarFactory in Ihrem Controller machen, indem Sie eine Reihe von spezifischen Zylindern für dieses Auto übergeben. Sie können keinen new CarService da CarService ein Objekt ist, keine function.

    Der Grund, warum Fabriken nicht so funktionieren:

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

    Und automatisch eine function für Sie zur Instanziierung zurückgeben, weil das dann nicht möglich ist (Dinge zum Prototyp / etc hinzufügen):

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

    Sehen Sie, wie es buchstäblich eine Fabrik ist, die ein Auto produziert.

    Die Schlussfolgerung aus seinem Blog ist ziemlich gut:

    Abschließend,

     --------------------------------------------------- | Provider| Singleton| Instantiable | Configurable| --------------------------------------------------- | Factory | Yes | Yes | No | --------------------------------------------------- | Service | Yes | No | No | --------------------------------------------------- | Provider| Yes | Yes | Yes | --------------------------------------------------- 
    1. Verwenden Sie den Dienst, wenn Sie nur ein einfaches Objekt wie einen Hash benötigen, zum Beispiel {foo; 1, bar: 2}. Es ist einfach zu programmieren, aber Sie können es nicht instanziieren.

    2. Verwenden Sie Factory, wenn Sie ein Objekt instanziieren müssen, dh neuen Kunden (), neuen Kommentar () usw.

    3. Verwenden Sie den Provider, wenn Sie ihn konfigurieren müssen. dh Test-URL, QA-URL, Produktions-URL.

    Wenn Sie feststellen, dass Sie gerade ein Objekt in der Fabrik zurückgeben, sollten Sie wahrscheinlich den Service nutzen.

    Tu das nicht:

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

    Verwenden Sie stattdessen den Dienst:

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

    Das Konzept für all diese Anbieter ist viel einfacher als es zunächst erscheint. Wenn Sie einen Anbieter sezieren und die verschiedenen Teile herausziehen, wird es sehr deutlich.

    Um es einfach zu sagen, jeder dieser Anbieter ist eine spezialisierte Version des anderen, in dieser Reihenfolge: provider > factory > value / constant / service .

    Solange der Anbieter das tut, was Sie können, können Sie den Anbieter weiter unten in der Kette verwenden, was dazu führen würde, weniger Code zu schreiben. Wenn es nicht das erreicht, was Sie wollen, können Sie die Kette hochgehen und Sie müssen nur mehr Code schreiben.

    Dieses Bild veranschaulicht, was ich meine, in diesem Bild sehen Sie den Code für einen Anbieter, mit den Abschnitten hervorgehoben, die Ihnen zeigen, welche Teile des Anbieters stattdessen verwendet werden könnten, um eine Fabrik, einen Wert usw. zu erstellen.

    AngularJS-Anbieter, Fabriken, Dienstleistungen usw. sind alle die gleichen Dinge http://sofde.miximages.com/angularjs/angularjs-provider-service-factory-highlight.png

    Für weitere Details und Beispiele aus dem Blog-Post, wo ich das Bild von erhalten haben, gehen Sie zu: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

    Sowohl die Fabrik als auch der Service führen zu Singleton-Objekten, die von den Providern konfiguriert und in Controller und Run-Blöcke injiziert werden können. Aus der Sicht des Eingeweihten besteht kein Unterschied, ob das Objekt aus einer Fabrik oder einer Dienstleistung stammt.

    Also, wann man eine Fabrik benutzt und wann man einen Service benutzt? Es läuft auf Ihre Kodierungspräferenz hinaus und sonst nichts. Wenn Sie das modulare JS-Muster mögen, dann gehen Sie für die Fabrik. Wenn Sie die Konstruktorfunktion (“class”) mögen, dann gehen Sie zum Service. Beachten Sie, dass beide Stile private Mitglieder unterstützen.

    Der Vorteil des Dienstes könnte darin liegen, dass er vom Standpunkt des OOP aus intuitiver ist: Erstellen Sie eine “class” und verwenden Sie in Verbindung mit einem Provider den gleichen Code für alle Module und variieren Sie das Verhalten der instanziierten Objekte einfach durch Bereitstellung verschiedene Parameter zum Konstruktor in einem Config-Block.

    Es gibt nichts, was eine Fabrik im Vergleich zu einem Service nicht tun oder besser machen kann. Und umgekehrt. Factory scheint nur beliebter zu sein. Der Grund dafür ist die Bequemlichkeit im Umgang mit privaten / öffentlichen Mitgliedern. In dieser Hinsicht wäre der Service ungeschickter. Wenn Sie einen Service codieren, neigen Sie dazu, Ihre Objektmitglieder über das Schlüsselwort “this” öffentlich zu machen und können plötzlich herausfinden, dass diese öffentlichen Mitglieder für private Methoden (dh innere functionen) nicht sichtbar sind.

     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 verwendet das Schlüsselwort “new”, um einen Dienst für Sie zu erstellen, sodass die Instanz, die Angular an den Controller übergibt, denselben Nachteil hat. Natürlich können Sie das Problem überwinden, indem Sie Folgendes verwenden:

     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' 

    Aber mit einer großen Service-Konstante würde dieser Code den Code schlecht lesbar machen. Darüber hinaus werden die Service-Prototypen keine privaten Mitglieder sehen, sondern nur die Öffentlichkeit.

     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' 

    Zusammenfassend ist die Verwendung von Factory bequemer. Als Fabrik hat diese Nachteile nicht. Ich würde empfehlen, es standardmäßig zu verwenden.

    Selbst wenn sie sagen, dass alle Dienste und Fabriken Singleton sind, stimme ich nicht 100 Prozent damit überein. Ich würde sagen, dass Fabriken keine Singles sind und das ist der Punkt meiner Antwort. Ich würde wirklich über den Namen nachdenken, der jede Komponente definiert (Service / Factory), ich meine:

    Eine Factory, weil es kein Singleton ist, können Sie so viele erstellen, wie Sie möchten, wenn Sie injizieren, also funktioniert es wie eine Fabrik von Objekten. Sie können eine Fabrik einer Entität Ihrer Domäne erstellen und mit diesen Objekten, die wie ein Objekt Ihres Modells sein könnten, komfortabler arbeiten. Wenn Sie mehrere Objekte abrufen, können Sie sie in diesen Objekten abbilden und sie kann als eine andere Ebene zwischen dem DDBB- und dem AngularJs-Modell fungieren. Sie können den Objekten Methoden hinzufügen, damit Sie Ihre Objekte ein wenig mehr auf Ihre AngularJs-App ausrichten.

    Inzwischen ist ein Dienst ein Singleton, also können wir nur 1 von einer Art erstellen, vielleicht nicht erstellen, aber wir haben nur 1 Instanz, wenn wir in einen Controller injizieren, also bietet ein Dienst mehr wie einen gemeinsamen Dienst (Ruheaufrufe, functionalität ..) zu den Controllern.

    Konzeptionell können Sie denken, dass Services einen Service bereitstellen. Factories können mehrere Instanzen (Objekte) einer class erstellen

    Dienstleistungen

    Syntax : module.service (‘serviceName’, function); Ergebnis : Wenn service_name als injizierbares Argument deklariert wird, wird Ihnen die tatsächliche functionsreferenz übergeben, die an module.service übergeben wurde.

    Verwendung : Dies kann nützlich sein, wenn Sie Dienstprogrammfunktionen freigeben möchten, die durch einfaches Anhängen von () an die Referenz der injizierten function aufgerufen werden können. Könnte auch mit injectedArg.call (this) oder ähnlichem ausgeführt werden.

    Fabriken

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

    Ergebnis : Wenn factoryName als injizierbares Argument deklariert wird, erhalten Sie den Wert, der zurückgegeben wird, indem die functionsreferenz aufgerufen wird, die an module.factory übergeben wurde.

    Verwendung : Kann nützlich sein, um eine ‘classn’-function zurückzugeben, die dann zum Erstellen von Instanzen neu erstellt werden kann.

    Anbieter

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

    Ergebnis : Wenn providerName als injizierbares Argument deklariert wird, erhalten Sie den Wert, der zurückgegeben wird, indem Sie die $ get-Methode der functionsreferenz aufrufen, die an module.provider übergeben wird.

    Verwendung : Kann nützlich sein, um eine ‘classn’-function zurückzugeben, die dann neu erstellt werden kann, um Instanzen zu erzeugen, aber das erfordert eine Art von Konfiguration, bevor sie injiziert wird. Vielleicht nützlich für classn, die in Projekten wiederverwendet werden können? Immer noch irgendwie verschwommen in diesem Fall.

    Kann so wie Sie wollen verwenden : Ob Objekt erstellen oder nur auf functionen von beiden zugreifen


    Sie können ein neues Objekt aus dem Service erstellen

     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(); }) 

    Hinweis :

    • Dienst standardmäßig gibt Objekt und nicht Konstruktorfunktion zurück.
    • Aus diesem Grund ist die Konstruktorfunktion auf diese Eigenschaft gesetzt.
    • Aufgrund dieses Dienstes wird Objekt zurückgegeben, aber aber aber innerhalb dieses Objekts wird Konstruktorfunktion, die verwendet werden, um neues Objekt zu erstellen;

    Sie können ein neues Objekt ab Werk erstellen

     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(); }) 

    Hinweis :

    • Factory gibt standardmäßig die Konstruktorfunktion und kein Objekt zurück.
    • Deshalb kann ein neues Objekt mit Konstruktorfunktion erstellt werden.

    Erstellen Sie Service für den Zugriff auf einfache functionen

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

    Erstellen Sie Factory für den Zugriff auf einfache functionen

     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() }) 

    Fazit :

    • Sie können sowohl die Art, wie Sie wollen, ob Sie ein neues Objekt erstellen möchten , als auch nur auf einfache functionen zugreifen
    • Es wird keinen performanceseinbruch geben, wenn einer über den anderen verwendet wird
    • Beide sind Singleton-Objekte und es wird nur eine Instanz pro App erstellt.
    • Es ist nur eine Instanz, an der die Referenz übergeben wird.
    • In der eckigen Dokumentation heißt die Fabrik Service und auch Service heißt Service .