AngularJS: Kiedy korzystać z usługi zamiast z fabryki

296

Proszę, znoś mnie tutaj. Wiem, że istnieją inne odpowiedzi, takie jak: AngularJS: usługa kontra dostawca vs fabryka

Jednak nadal nie mogę ustalić, kiedy skorzystasz z usługi nad fabryką.

Z tego, co mogę powiedzieć, fabryka jest powszechnie używana do tworzenia „wspólnych” funkcji, które mogą być wywoływane przez wiele kontrolerów: Tworzenie wspólnych funkcji kontrolera

Dokumenty Angular wydają się preferować fabrykę niż serwis. Odnoszą się nawet do „serwisu”, gdy korzystają z fabryki, co jest jeszcze bardziej mylące! http://docs.angularjs.org/guide/dev_guide.services.creating_services

Kiedy więc skorzystać z usługi?

Czy jest coś, co jest możliwe lub znacznie łatwiejsze do wykonania z serwisem?

Czy dzieje się coś innego za kulisami? Różnice w wydajności / pamięci?

Oto przykład. Poza metodą deklaracji wydają się identyczne i nie mogę zrozumieć, dlaczego miałbym to robić jedno na drugim. http://jsfiddle.net/uEpkE/

Aktualizacja: Z odpowiedzi Thomasa wynika, że ​​usługa służy prostszej logice, a fabryka bardziej złożonej logice metodami prywatnymi, więc zaktualizowałem poniższy kod skrzypiec i wydaje się, że oba są w stanie obsługiwać funkcje prywatne?

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()
    ];
}
użytkownik1941747
źródło
Oczywiście usługa obsługuje prywatne, ale jeśli poprawnie przeczytasz mój post, jest to czysto kodowy styl: możemy również skorzystać z nowego zakresu leksykalnego, aby zasymulować zmienne „prywatne”. To „SIMULATE”
Thomas Pons,
Uważam tę dyskusję za bardzo przydatną stackoverflow.com/questions/15666048/...
Anand Gupta
2
Jest tu również kilka dobrych odpowiedzi .
Mistalis

Odpowiedzi:

280

Wyjaśnienie

Masz tutaj różne rzeczy:

Pierwszy:

  • Jeśli korzystasz z usługi, otrzymasz instancję funkcji ( thissłowo kluczowe „ ”).
  • Jeśli korzystasz z fabryki, otrzymasz wartość zwracaną przez wywołanie odwołania do funkcji (instrukcja return w fabryce).

ref: angular.service vs. angular.factory

Druga:

Należy pamiętać, że wszyscy dostawcy w AngularJS (wartość, stała, usługi, fabryki) są singletonami!

Trzeci:

Używanie jednego lub drugiego (usługi lub fabryki) dotyczy stylu kodu. Ale powszechnym sposobem w AngularJS jest korzystanie z fabryki .

Dlaczego ?

Ponieważ „Metoda fabryczna jest najczęstszym sposobem wprowadzania obiektów do systemu wstrzykiwania zależności AngularJS. Jest bardzo elastyczna i może zawierać wyrafinowaną logikę tworzenia. Ponieważ fabryki są regularnymi funkcjami, możemy również skorzystać z nowego zakresu leksykalnego do symulacji” prywatnego „zmienne. Jest to bardzo przydatne, ponieważ możemy ukryć szczegóły implementacji danej usługi.”

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


Stosowanie

Usługa: może być przydatny do udostępniania funkcji narzędziowych, które można wywołać, po prostu dołączając ()do wstrzykniętego odwołania do funkcji. Można go również uruchomić z injectedArg.call(this)podobnym.

Fabryka: może być przydatny do zwracania funkcji „klasy”, która może być następnie nowa w celu tworzenia instancji.

Więc skorzystaj z fabryki, gdy masz złożoną logikę w swojej usłudze i nie chcesz ujawniać tej złożoności .

W innych przypadkach, jeśli chcesz zwrócić instancję usługi, po prostu skorzystaj z usługi .

Ale z czasem przekonasz się, że w 80% przypadków skorzystasz z fabryki.

Aby uzyskać więcej informacji: http://blog.manishchhabra.com/2013/09/angularjs-service-vs-factory-with-example/


AKTUALIZACJA :

Doskonały post tutaj: http://iffycan.blogspot.com.ar/2013/05/angular-service-or-factory.html

„Jeśli chcesz, aby twoja funkcja była wywoływana jak normalna , skorzystaj z fabryki . Jeśli chcesz, aby twoja funkcja została utworzona przez nowego operatora, skorzystaj z usługi. Jeśli nie znasz różnicy, skorzystaj z fabryki”.


AKTUALIZACJA :

Zespół AngularJS wykonuje swoją pracę i wyjaśnia: http://docs.quarejs.org/guide/providers

I z tej strony:

„Fabryka i usługa są najczęściej używanymi przepisami. Jedyna różnica między nimi polega na tym, że przepis usługi działa lepiej dla obiektów niestandardowego typu, podczas gdy fabryka może tworzyć prymitywy i funkcje JavaScript”.

Thomas Pons
źródło
7
Re First: Czytam to wszędzie, ale nie rozumiem praktycznych konsekwencji tego. Sądzę, że z twojej odpowiedzi nie ma praktycznej różnicy „w większości”? Dzięki za referencje do książki!
user1941747,
To proste, jeśli twoja usługa jest naprawdę złożona i potrzebujesz prywatnych metod, a obiekty korzystają z fabryki
Thomas Pons,
1
Zauważyłem, że dodałeś „Jeśli chcesz zwrócić instancję usługi, po prostu skorzystaj z usługi”. Moje dalsze pytanie brzmi: KIEDY chcesz zwrócić instancję usługi? Próbuję znaleźć tutaj konkretny przypadek użycia.
user1941747,
12
„Ponieważ fabryki są funkcjami regularnymi, możemy również skorzystać z nowego zakresu leksykalnego do symulacji„ prywatnych ”zmiennych.” - to nie jest specyficzne dla fabryk, możesz zrobić to samo z usługami.
pootzko
Wygląda na to, że zespół Google woli serwis niż fabryka, co jeszcze bardziej komplikuje sprawę! google-styleguide.googlecode.com/svn/trunk/…
xzhang 30.01.2015
111

allernhwkim pierwotnie opublikowane odpowiedź na to pytanie, prowadząc do swojego bloga , jednak moderator ją usunął. To jedyny znaleziony przeze mnie post, który nie tylko mówi ci, jak zrobić to samo z usługą, dostawcą i fabryką, ale także mówi, co możesz zrobić z dostawcą, czego nie możesz zrobić z fabryką, i fabryka, której nie da się zrobić z usługą.

Bezpośrednio z jego bloga:

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

To pokazuje, jak CarService zawsze produkuje samochód z 4 cylindrami, nie można go zmienić dla poszczególnych samochodów. Podczas gdy CarFactory zwraca funkcję, więc możesz to zrobićnew CarFactory w swoim kontrolerze, przekazując szereg cylindrów właściwych dla tego samochodu. Nie możesz tego zrobić, new CarServiceponieważ CarService to obiekt, a nie funkcja.

Powody, dla których fabryki nie działają w ten sposób:

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

I automatycznie zwraca funkcję do utworzenia, ponieważ wtedy nie możesz tego zrobić (dodaj rzeczy do prototypu / etc):

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

Zobacz, jak dosłownie jest to fabryka produkująca samochód.

Wniosek z jego bloga jest całkiem niezły:

Podsumowując

---------------------------------------------------  
| Provider| Singleton| Instantiable | Configurable|
---------------------------------------------------  
| Factory | Yes      | Yes          | No          |
---------------------------------------------------  
| Service | Yes      | No           | No          |
---------------------------------------------------  
| Provider| Yes      | Yes          | Yes         |       
---------------------------------------------------  
  1. Skorzystaj z usługi, gdy potrzebujesz tylko prostego obiektu, takiego jak Hash, na przykład {foo; 1, bar: 2} Kodowanie jest łatwe, ale nie można go utworzyć.

  2. Użyj Factory, gdy potrzebujesz utworzyć instancję obiektu, tj. Nowego klienta (), nowego komentarza () itp.

  3. Użyj dostawcy, gdy musisz go skonfigurować. tj. adres testowy, adres QA, adres produkcyjny.

Jeśli zauważysz, że zwracasz obiekt w fabryce, prawdopodobnie powinieneś skorzystać z usługi.

Nie rób tego:

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

Zamiast tego skorzystaj z usługi:

app.service('CarService', function() {
    this.numCylinder = 4;
});
Jonathan.
źródło
11
jest to dla mnie bardzo pomocne. +1 dla tabeli porównawczej
Vu Anh
5
jeśli zdefiniujesz funkcję serwisową za pomocą jednego parametru numCylinder, będzie ona miała taką samą elastyczność jak metoda fabryczna
Ovi
idź i poczytaj blog na blogu, i marnuj swój czas, próbując odgadnąć kąt, jeśli znasz javascript po przeczytaniu tego posta, całkowicie zrozumiesz różnicę między tym.
ncubica
4
Bardzo zaskoczony ! Polecasz bloga tutaj i obaj mówią coś zupełnie przeciwnego. Mówisz: Factory - Instantiable - Tak Blog mówi: Factory - Instantiable - Nie
Devesh M
1
Zgadzam się z @Devesh. Myślę, że masz pomieszane wystąpienia. Z postu na blogu: „Tylko w fabryce nie można tego osiągnąć, ponieważ nie można utworzyć instancji fabryki”.
Matt
20

Koncepcja wszystkich tych dostawców jest znacznie prostsza niż się początkowo wydaje. Jeśli zrobisz sekcję dostawcy i wyciągniesz różne części, stanie się to bardzo jasne.

Po prostu każdy z tych dostawców jest wyspecjalizowanym wersja z drugiej strony, w tej kolejności: provider> factory> value/ constant/service .

Tak długo, jak dostawca robi wszystko, co możesz, możesz użyć tego dostawcy w dalszej części łańcucha, co spowodowałoby mniej pisania kodu. Jeśli to nie spełni twoich oczekiwań, możesz pójść w górę łańcucha i po prostu będziesz musiał napisać więcej kodu.

Ten obraz ilustruje, co mam na myśli, na tym obrazku zobaczysz kod dostawcy, z podświetlonymi częściami pokazującymi, które części dostawcy mogłyby zostać użyte do utworzenia fabryki, wartości itp.

Dostawcy, fabryki, usługi itp. AngularJS są tym samym
(źródło: simplygoodcode.com )

Aby uzyskać więcej informacji i przykładów z postu na blogu, z którego dostałem obraz, przejdź do: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

Luis Perez
źródło
8

Zarówno fabryka, jak i usługa dają w wyniku obiekty singletonowe, które mogą być konfigurowane przez dostawców i wprowadzane do kontrolerów i uruchamiają bloki. Z punktu widzenia osoby wstrzykiwanej nie ma absolutnie żadnej różnicy, czy przedmiot pochodzi z fabryki, czy z usługi.

Kiedy więc skorzystać z fabryki, a kiedy skorzystać z usługi? Sprowadza się to do twoich preferencji kodowania i nic więcej. Jeśli podoba Ci się modułowy wzór JS, przejdź do fabryki. Jeśli podoba Ci się styl funkcji konstruktora („klasa”), przejdź do usługi. Pamiętaj, że oba style obsługują członków prywatnych.

Zaletą usługi może być to, że jest ona bardziej intuicyjna z punktu widzenia OOP: utwórz „klasę” i, we współpracy z dostawcą, ponownie wykorzystaj ten sam kod w modułach i zmień zachowanie tworzonych obiektów po prostu poprzez dostarczenie inne parametry niż konstruktor w bloku konfiguracji.

Steve Lang
źródło
Czy możesz podać przykład tego, co rozumiesz przez podanie konstruktorowi różnych parametrów w bloku konfiguracji? Jak podać parametry, jeśli jest to tylko usługa lub fabryka. Co rozumiesz przez „w połączeniu z dostawcą”? Możliwość konfiguracji pozwala mi sądzić, że wiele moich obiektów powinno być dostawcami w porównaniu z fabrykami lub usługami.
timbrown
2

Nie ma nic, co Fabryka nie mogłaby zrobić lub lepiej w porównaniu z Usługą. I wice wiersz. Fabryka wydaje się być bardziej popularna. Powodem tego jest wygoda w obsłudze członków prywatnych / publicznych. Służba byłaby pod tym względem bardziej niezdarna. Podczas kodowania usługi zwykle upubliczniasz członków swojego obiektu za pomocą słowa kluczowego „this” i możesz nagle odkryć, że ci publiczni członkowie nie są widoczni dla metod prywatnych (tj. Funkcji wewnętrznych).

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 używa słowa kluczowego „new”, aby utworzyć dla Ciebie usługę, więc instancja Angular przekazana do kontrolera będzie miała tę samą wadę. Oczywiście możesz rozwiązać ten problem, używając tego / tego:

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'  

Ale przy dużej stałej usługi, to \ spowoduje, że kod będzie słabo czytelny. Ponadto prototypy usługi nie będą widzieć członków prywatnych - będą dla nich dostępne tylko publiczne:

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'

Podsumowując, korzystanie z Factory jest wygodniejsze. Ponieważ Factory nie ma tych wad. Polecam używanie go domyślnie.

Andrew Krook
źródło
Ta odpowiedź ma kilka problemów. Po pierwsze, ten post pokazuje koncepcję JavaScript w zakresie zakresu leksykalnego, a nie jak działają usługi AngularJS. Po drugie, myapp.service(...)całkowicie brakuje kontekstu połączeń . Gdzie new Service()należy wywoływać, w funkcji usługi lub w miejscu, w którym usługa jest wstrzykiwana. Trzecia lista jest po prostu niemożliwa w kontekście myapp.service ('Service', function() {...}).
lanoxx
2

Nawet jeśli mówią, że wszystkie usługi i fabryki są jednoosobowe, nie zgadzam się z tym w 100 procentach. Powiedziałbym, że fabryki nie są singletonami i to jest sens mojej odpowiedzi. Naprawdę pomyślałbym o nazwie, która definiuje każdy komponent (Service / Factory), mam na myśli:

fabryka ponieważ nie jest pojedyncza, można utworzyć tyle, ile chcesz i kiedy wstrzykiwać, tak to działa jak fabryka obiektów. Możesz stworzyć fabrykę encji w swojej domenie i pracować bardziej komfortowo z tymi obiektami, które mogą być jak obiekt twojego modelu. Gdy pobierzesz kilka obiektów, możesz zmapować je w tych obiektach i może on stanowić rodzaj kolejnej warstwy między DDBB a modelem AngularJs. Możesz dodawać metody do obiektów, dzięki czemu zorientujesz się na obiekty nieco bardziej w swojej aplikacji AngularJs.

Tymczasem usługa jest singletonem, więc możemy stworzyć tylko jeden, może nie utworzyć, ale mamy tylko 1 instancję, kiedy wstrzykiwamy kontroler, więc usługa bardziej przypomina wspólną usługę (wywołania reszty, funkcjonalność ...) do kontrolerów.

Koncepcyjnie możesz myśleć, że usługi świadczą usługi, fabryki mogą tworzyć wiele instancji (obiektów) klasy

francisco J Jimenez Garcia
źródło
0

Usługi

Składnia : module.service ('serviceName', funkcja); Wynik : deklarując serviceName jako argument do wstrzyknięcia, otrzymasz rzeczywiste odwołanie do funkcji przekazane do module.service.

Użycie : Może być przydatny do udostępniania funkcji narzędziowych, które można wywołać, po prostu dodając () do wstrzykniętego odwołania do funkcji. Można go również uruchomić za pomocą injectedArg.call (this) lub podobnego.

Fabryki

Składnia : module.factory ('nazwa_fabryki', funkcja);

Wynik : deklarując nazwę fabryczną jako argument do wstrzyknięcia, otrzymasz wartość zwracaną przez wywołanie odwołania do funkcji przekazanego do module.factory.

Użycie : Może być przydatny do zwrócenia funkcji „klasy”, którą można następnie zmienić w celu utworzenia instancji.

Dostawcy

Składnia : module.provider ('dostawcaName', funkcja);

Wynik : deklarując nazwę dostawcy jako argument do wstrzyknięcia, otrzymasz wartość zwracaną przez wywołanie metody $ get odwołania do funkcji przekazanej do module.provider.

Użycie : Może być przydatny do zwracania funkcji „klasy”, którą można następnie zmienić w celu utworzenia instancji, ale która wymaga pewnej konfiguracji przed wstrzyknięciem. Być może przydatne w przypadku klas, które można wielokrotnie wykorzystywać w różnych projektach? Nadal trochę niejasno w tym.

Nishant Upadhyay
źródło
0

Może korzystać z obu sposobów : tworzyć obiekty lub po prostu uzyskiwać dostęp do funkcji z obu


Możesz utworzyć nowy obiekt z usługi

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

Uwaga :

  • usługa domyślnie zwraca obiekt, a nie funkcję konstruktora.
  • Dlatego właśnie funkcja konstruktora jest ustawiona na właściwość this.model.
  • Ze względu na tę usługę zwróci obiekt, ale ale w tym obiekcie znajdzie się funkcja konstruktora, która zostanie użyta do utworzenia nowego obiektu;

Możesz utworzyć nowy obiekt z fabryki

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

Uwaga :

  • fabryka domyślnie zwraca funkcję konstruktora, a nie obiekt.
  • Dlatego właśnie można utworzyć nowy obiekt za pomocą funkcji konstruktora.

Utwórz usługę, aby uzyskać dostęp do prostych funkcji

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

.controller('MyService', function ($scope,carservice) { 
    carservice.createCar()
})

Utwórz fabrykę, aby uzyskać dostęp do prostych funkcji

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

Wniosek:

  • możesz używać w dowolny sposób aby utworzyć nowy obiekt lub po prostu uzyskać dostęp do prostych funkcji
  • Nie będzie żadnego spadku wydajności, używając jednego nad drugim
  • Oba są obiektami singletonowymi i dla aplikacji tworzona jest tylko jedna instancja.
  • Będąc tylko jedną instancją w każdym miejscu, w którym przekazywana jest ich referencja.
  • W dokumentacji kątowej fabryka nazywana jest usługą, a także usługa nazywana jest usługą .
Vijay
źródło
0

Fabryka i serwis są najczęściej stosowaną metodą. Jedyna różnica między nimi polega na tym, że metoda Service działa lepiej w przypadku obiektów wymagających hierarchii dziedziczenia, podczas gdy fabryka może tworzyć prymitywy i funkcje JavaScript.

Funkcja Provider jest podstawową metodą, a wszystkie pozostałe są po prostu cukrem syntaktycznym. Potrzebujesz go tylko wtedy, gdy budujesz fragment kodu wielokrotnego użytku, który wymaga globalnej konfiguracji.

Istnieje pięć metod tworzenia usług: wartość, fabryka, usługa, dostawca i stała. Możesz dowiedzieć się więcej na temat tej usługi kątowej , w tym artykule wyjaśniono wszystkie te metody za pomocą praktycznych przykładów demonstracyjnych.

.

użytkownik3114005
źródło