Services vs. Factories in Angular
EDIT 2016. Megjegyezzük, hogy ez a bejegyzés, amely egy 2015-ös bejegyzés újraközlése, az Angular 1-ről szól. Már nem foglalkozom frontenddel, így nem garantálom, hogy ez a poszt releváns az Angular 2-re ;).
A Hack Reactor egyik osztálytársammal nemrég építettünk egy magas vérnyomás kezelési kalkulátort a Moxe Health számára, egy izgalmas Rock Health cég számára, amely egy olyan adatbázis integrációs rendszert és API-t épít, amely lehetővé teszi bármely fejlesztő számára, hogy hozzáférjen a Moxe hálózatában lévő bármely kórház elektronikus orvosi nyilvántartásához. Izgatottan beszélek a Moxe-ról és a projektről egy másik bejegyzésben. Az alkalmazás front-endjét Angularban építettük, egy erős front-end keretrendszerben, adatkötéssel és más fantasztikus funkciókkal. Az egyik dolog, ami zavarba ejtő volt, az az volt, hogy mikor használjunk szolgáltatásokat vs. gyárakat. A Stack Overflownak van egy jó szála a kettő közötti különbségről, de kihagy néhány analógiát, amelyek szerintem hasznosak lehetnek a fejlesztők számára, akik még mindig a Javascript-ismereteiket szilárdítják.
Ebben a bejegyzésben meg fogod tanulni a kettő közötti különbséget.
TLDR – a gyárak és a szolgáltatások nagyjából ugyanazzal a funkcionalitással rendelkeznek, ami a módszerek és tulajdonságok példányosításának és beágyazásának képességét illeti, hasonlóan a funkcionális példányosítás és a pszeudoklasszikus példányosítási minták hasonló képességeihez. Az Angular közösségben nincs preferencia az egyik vagy a másik használatára. A gyári és szolgáltatási receptek csak szintaktikai cukrot jelentenek a szolgáltatói recept tetején. Tehát a kérdés, amit fel kell tenned magadnak, általában nem az, hogy “gyárakat vagy szolgáltatásokat használjak?”, hanem az, hogy “funkcionális instantiálást vagy pszeudoklasszikus instantiálást használjak?”.”
Ez a magas szintű megértésen kívül a legjelentősebb különbség az, hogy az eltérő példányosítási minták miatt a gyárak primitíveket és függvényeket adhatnak vissza, a szolgáltatások viszont nem.
Primitívek, függvények és objektumok, ó, te jó ég!
Nézd meg ezt a JSFiddle-t. Köszönet Epokknak a kód nagy részének biztosításáért. Csináltam egy pár módosítást, ami megint csak segít az Angularhoz újonnan érkező fejlesztőknek, hogy itt fúrják le a különbséget. Ha új a JSFiddle, ez egy olyan eszköz, amely lehetővé teszi, hogy könnyen tesztelni kölcsönhatások között a javascript, html, és css fájlokat. Így játszhatsz a kóddal, és nem írja felül az eredeti kódot a linkben.
A példában mind a szolgáltatás, mind a gyár ugyanazzal a funkcionalitással rendelkezik, hogy visszaadja a “Hello World!” sztringet. A különbség az, hogy hogyan csinálják.
A szolgáltatás egy objektumot példányosít, és az objektum “sayHello” tulajdonságához hozzárendeli a “Hello World!”-t visszaadó függvényt:
this.sayHello = function() { return "Hello, World!" };
A metódus ezután meghívásra kerül a vezérlőben: helloWorldFromService.sayHello().
A gyár visszaad egy függvényt, amely visszaadja a “Hello World!”-t:
return function() { return "Hello, World!" };
A függvény ezután meghívásra kerül a vezérlőben: helloWorldFromFactory(). Figyeljük meg, hogy a gyár hivatkozása a visszaadott függvényre mutat, nem pedig egy olyan objektum tulajdonságára, amelynek értéke egy függvény, mint a szolgáltatási példában. Egy szolgáltatás soha nem tudná ezt megtenni, mert egy szolgáltatásnak egy üres objektumot kell példányosítania, amelynek a szolgáltatás függvénytestén belüli hivatkozása ‘this’. A szolgáltatások mindig objektumokat adnak vissza.
Itt van a gyáraknak az a része, ami zavaró lehet. A factory is visszaadhat egy objektumot, amelynek van egy ‘sayHello’ metódusa, hasonlóan a szolgáltatáshoz:
return { sayHello: function() { return "Hello, World!" } };
amelyet a vezérlőben pontosan úgy hívnánk meg, mint a szolgáltatás sayHello függvényét: helloWorldFromFactory.sayHello().
Az utóbbi factory formátum akkor hasznos, ha több metódust akarsz egy factoryben:
return { sayHello: function() { return "Hello, World!" }, sayGoodbye: function() { return "Goodbye, World!" } };
A kulcs itt is az, hogy ne ragadj le azon, hogy Angularban kódolsz, és ne feledd, hogy a szolgáltatások és a factories közötti különbségek nagyrészt ugyanazok, mint a pszeudoklasszikus példányosítás és a funkcionális példányosítás közötti különbségek.
Forráskód a kíváncsiaknak
Itt az Angular forráskódja, amely bemutatja, hogy a szolgáltatások &gyárak az általánosabb providers funkcióra vannak rétegezve:
//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, ); }
Mind a szolgáltatás, mind a gyár singletonokat hoz létre. Alapvető funkcionális vs. pszeudoklasszikus öröklési minták itt. A factory azt adja vissza, amit a factoryFn visszaad.
A service egy pszeudo-osztály példányát adja vissza. A pszeudo-osztály konstruktorát átadjuk az Angular szolgáltatásépítő service() parancsának. Az a tény, hogy a konstruktor átadásra kerül a service builder service-nek (return $injector.instantiate(constructor)) zavaró lehet, de gondoljunk csak arra, hogy return new constructor().
Boldog kódolást!
Leave a Reply