Services vs. Factories in Angular

EDIT 2016. Zauważ, że ten post, który jest repostem postu z 2015 roku, dotyczy Angulara 1. Nie robię już frontend, więc nie ma gwarancji, że ten post jest istotny dla Angular 2 ;).

Jeden z moich kolegów z klasy Hack Reactor i ja ostatnio zbudowaliśmy kalkulator leczenia wysokiego ciśnienia krwi dla Moxe Health, ekscytującej firmy Rock Health, która buduje system integracji baz danych i API, który pozwoli każdemu programiście uzyskać dostęp do elektronicznej dokumentacji medycznej dowolnego szpitala w sieci Moxe. Jestem podekscytowany, że będę mógł opowiedzieć o Moxe i projekcie w innym poście. Zbudowaliśmy front-end aplikacji w Angular, potężnym frameworku front-end z wiązaniem danych i innymi niesamowitymi funkcjami. Jedną z rzeczy, która była myląca było to, kiedy używać usług vs. fabryk. Stack Overflow ma dobry wątek na temat różnic między tymi dwoma, ale pomija pewne analogie, które moim zdaniem są przydatne dla programistów wciąż cementujących swoją wiedzę Javascript.

W tym poście dowiesz się, jaka jest różnica między tymi dwoma.

TLDR – fabryki i usługi mają całkiem sporo tej samej funkcjonalności pod względem ich zdolności do instancjonowania i kapsułkowania metod i właściwości, podobnie jak funkcjonalne wzorce instancyjne i pseudoklasyczne wzorce instancyjne mają podobne zdolności. Nie ma żadnych preferencji w społeczności Angulara, aby używać jednego lub drugiego. Receptury fabryk i usług są tylko cukrem syntaktycznym na wierzchu receptury dostawcy. Więc pytanie, które powinieneś sobie zadać, to zazwyczaj nie „czy powinienem używać fabryk lub usług?” to „czy powinienem używać funkcjonalnej instantyzacji lub pseudoklasycznej instantyzacji?”

Innym niż to wysokopoziomowe zrozumienie, najbardziej znaczącą różnicą jest to, że w wyniku różnicy w ich wzorcach instancyjnych, fabryki mogą zwracać prymitywy i funkcje, ale usługi nie mogą.

Prymitywy, funkcje i obiekty, o mój!

Sprawdź to JSFiddle. Słowa uznania dla Epokk’a za dostarczenie większości kodu. Zrobiłem kilka modyfikacji, które ponownie, naprawdę pomagają programistom nowym w Angular, aby wiercić w dół na różnicy tutaj. Jeśli jesteś nowy w JSFiddle, jest to narzędzie, które pozwala na łatwe testowanie interakcji między twoim javascript, html i plikami css. Możesz więc bawić się kodem, a nie będzie on nadpisywał oryginalnego kodu w odnośniku.

Obie usługi i fabryki w tym przykładzie mają tę samą funkcjonalność zwracania ciągu „Hello World!”. Różnica polega na tym, jak to robią.

Usługa instancjonuje obiekt i przypisuje funkcję zwracającą „Hello World!” do właściwości „sayHello” tego obiektu:

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

Metoda ta jest następnie wywoływana w kontrolerze: helloWorldFromService.sayHello().

Fabryka zwraca funkcję, która zwraca „Hello World!”:

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

Funkcja ta jest następnie wywoływana w kontrolerze: helloWorldFromFactory(). Zauważ, że referencja fabryki wskazuje na zwróconą funkcję, a nie na właściwość obiektu, którego wartością jest funkcja, jak w przykładzie z usługą. Usługa nigdy nie mogłaby tego zrobić, ponieważ usługa musi zainicjować pusty obiekt, którego referencją w ciele funkcji usługi jest 'this’. Usługi zawsze zwracają obiekty.

Oto część fabryk, która może być myląca. Fabryka może również zwrócić obiekt, który ma metodę 'sayHello’, podobnie jak usługa:

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

Którą wywołałbyś w kontrolerze dokładnie tak, jak wywołałbyś funkcję sayHello usługi: helloWorldFromFactory.sayHello().

Ten ostatni format fabryki jest przydatny, gdy chcesz mieć wiele metod w fabryce:

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

Powtarzam, kluczem jest tutaj nie dać się złapać na tym, że kodujesz w Angular, i pamiętać, że różnice między usługami i fabrykami są w przeważającej części takie same jak różnice między pseudoklasyczną instancją a funkcjonalną instancją.

Kod źródłowy dla ciekawskich

Tutaj jest kod źródłowy Angular, demonstrujący, że usługi & fabryki są warstwowe na wierzchu bardziej ogólnej funkcji dostawców:

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

Zarówno usługa, jak i fabryka tworzą singletony. Podstawowe funkcjonalne vs. pseudoklasyczne wzorce dziedziczenia tutaj. Fabryka zwraca to, co zwraca factoryFn.

Usługa zwraca instancję pseudoklasy. Konstruktor pseudoklasy jest przekazywany do konstruktora usługi Angulara service(). Fakt, że konstruktor jest przekazywany do usługi konstruktora usługi (return $injector.instantiate(constructor)) może być mylący, ale po prostu pomyśl o tym jako o return new constructor().

Szczęśliwe kodowanie!

.

Leave a Reply