631 Stimmen

Verwirrt über Service vs. Fabrik

So wie ich es verstehe, gebe ich innerhalb einer Fabrik ein Objekt zurück, das in einen Controller injiziert wird. Wenn ich mich in einem Dienst befinde, behandle ich das Objekt mit this und nichts zurückgeben.

Ich bin davon ausgegangen, dass ein Dienst immer ein Singleton und dass ein neues Fabrikobjekt wird in jeden Controller injiziert. Doch wie sich herausstellt, ist ein Fabrikobjekt auch ein Singleton?

Beispielcode zur Demonstration:

var factories = angular.module('app.factories', []);
var app = angular.module('app',  ['ngResource', 'app.factories']);

factories.factory('User', function () {
  return {
    first: 'John',
    last: 'Doe'
  };
});

app.controller('ACtrl', function($scope, User) {
  $scope.user = User;
});

app.controller('BCtrl', function($scope, User) {
  $scope.user = User;
});

Beim Wechsel user.first en ACtrl es stellt sich heraus, dass user.first en BCtrl wird ebenfalls geändert, z. B. User ein Singleton ist?

Meine Annahme war, dass eine neue Instanz in einem Controller mit einer Fabrik injiziert wurde?

27voto

Anand Punkte 4483

Ergänzend zur ersten Antwort denke ich, dass .service() für Leute ist, die ihren Code in einem eher objektorientierten Stil (C#/Java) geschrieben haben (unter Verwendung dieses Schlüsselworts und der Instanziierung eines Objekts über die Funktion prototype/Constructor).

Factory ist für Entwickler gedacht, die Code schreiben, der eher dem javascript/funktionalen Stil der Codierung entspricht.

Werfen Sie einen Blick auf den Quellcode der Methoden .service und .factory in angular.js - intern rufen sie alle die Methode provider auf:

  function provider(name, provider_) {
    if (isFunction(provider_)) {
      provider_ = providerInjector.instantiate(provider_);
    }
    if (!provider_.$get) {
      throw Error('Provider ' + name + ' must define $get factory method.');
    }
    return providerCache[name + providerSuffix] = provider_;
  }

  function factory(name, factoryFn) { \
    return provider(name, { $get: factoryFn }); 
  }

  function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
  }

25voto

bingles Punkte 10549

Ganz einfach:

.service - die registrierte Funktion wird als Konstruktor aufgerufen (auch bekannt als "newed")

.factory - die registrierte Funktion wird als einfache Funktion aufgerufen

Beide werden einmal aufgerufen, wodurch ein Singleton-Objekt entsteht, das in andere Komponenten Ihrer Anwendung injiziert wird.

20voto

Luis Perez Punkte 26807

Alle Anbieter arbeiten auf dieselbe Weise. Die verschiedenen Methoden service , factory , provider können Sie das Gleiche mit weniger Code erreichen.

P.S. Außerdem gibt es value y constant .

Jeder Sonderfall in der Kette beginnend mit provider und endet mit value hat eine zusätzliche Einschränkung. Wenn Sie sich also für eine der beiden Varianten entscheiden wollen, müssen Sie sich fragen, mit welcher Sie das Gewünschte mit weniger Code erreichen können.

Hier ist ein Bild, das Ihnen zeigt, was ich meine:

enter image description here

Eine Aufschlüsselung und einen Leitfaden finden Sie in dem Blogbeitrag, aus dem ich dieses Bild habe:

http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

13voto

Shivprasad Koirala Punkte 25296

"Factory" und "Service" sind verschiedene Möglichkeiten, DI (Dependency Injection) in Angular durchzuführen.

Wenn wir also DI mit "Service" definieren, wie im folgenden Code gezeigt. Dadurch wird eine neue GLOBALE Instanz des "Logger"-Objekts erstellt und in die Funktion injiziert.

app.service("Logger", Logger); // Injects a global object

Wenn Sie DI mit Hilfe einer "Fabrik" definieren, wird keine Instanz erzeugt. Sie übergibt lediglich die Methode und später muss der Verbraucher intern die Fabrik für Objektinstanzen aufrufen.

app.factory("Customerfactory", CreateCustomer);

Nachfolgend ein einfaches Bild, das visuell zeigt, wie sich der DI-Prozess für "Service" von "Factory" unterscheidet.

enter image description here

Factory sollte verwendet werden, wenn wir verschiedene Arten von Objekten je nach Szenario erstellen wollen. Zum Beispiel wollen wir je nach Szenario ein einfaches "Kunden"-Objekt oder ein "Kunde" mit "Adresse"-Objekt oder ein "Kunde" mit "Telefon"-Objekt erstellen. Hier eine ausführliche Erklärung zu diesem Absatz

Service sollte verwendet werden, wenn wir Dienstprogramm oder gemeinsam genutzte Funktionen wie Dienstprogramm, Logger, Fehlerhandler usw. injiziert werden müssen.

13voto

Hier sind einige weitere Beispiele für Dienstleistungen und Fabriken, die den Unterschied zwischen ihnen verdeutlichen können. Grundsätzlich wird bei einem Dienst "new ..." aufgerufen, er ist bereits instanziiert. Eine Fabrik wird nicht automatisch instanziiert.

Grundlegende Beispiele

Rückgabe eines Klassenobjekts, das eine einzige Methode hat

Hier ist ein Dienst, der eine einzige Methode hat:

angular.service('Hello', function () {
  this.sayHello = function () { /* ... */ };
});

Hier ist eine Fabrik, die ein Objekt mit einer Methode zurückgibt:

angular.factory('ClassFactory', function () {
  return {
    sayHello: function () { /* ... */ }
  };
});

Rückgabe eines Wertes

Eine Fabrik, die eine Liste von Zahlen zurückgibt:

angular.factory('NumberListFactory', function () {
  return [1, 2, 3, 4, 5];
});

console.log(NumberListFactory);

Ein Dienst, der eine Liste von Zahlen zurückgibt:

angular.service('NumberLister', function () {
  this.numbers = [1, 2, 3, 4, 5];
});

console.log(NumberLister.numbers);

Die Ausgabe ist in beiden Fällen die gleiche, nämlich eine Liste von Zahlen.

Fortgeschrittene Beispiele

"Klassen"-Variablen mit Hilfe von Fabriken

In diesem Beispiel definieren wir eine CounterFactory, die einen Zähler inkrementiert oder dekrementiert, und Sie können den aktuellen Zählerstand abfragen oder ermitteln, wie viele CounterFactory-Objekte erstellt worden sind:

angular.factory('CounterFactory', function () {
  var number_of_counter_factories = 0; // class variable

  return function () {
    var count = 0; // instance variable
    number_of_counter_factories += 1; // increment the class variable

    // this method accesses the class variable
    this.getNumberOfCounterFactories = function () {
      return number_of_counter_factories;
    };

    this.inc = function () {
      count += 1;
    };
    this.dec = function () {
      count -= 1;
    };
    this.getCount = function () {
      return count;
    };
  }

})

Wir verwenden die CounterFactory um mehrere Zähler zu erstellen. Wir können auf die Klassenvariable zugreifen, um zu sehen, wie viele Zähler erstellt wurden:

var people_counter;
var places_counter;

people_counter = new CounterFactory();
console.log('people', people_counter.getCount());
people_counter.inc();
console.log('people', people_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());

places_counter = new CounterFactory();
console.log('places', places_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());
console.log('counters', places_counter.getNumberOfCounterFactories());

Die Ausgabe dieses Codes ist:

people 0
people 1
counters 1
places 0
counters 2
counters 2

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X