Java konstruktorok vs statikus gyári módszerek

1. Áttekintés

A Java-konstruktorok az alapértelmezett mechanizmusok a teljesen inicializált osztálypéldányok lekérésére. Végül is biztosítják a függőségek injektálásához szükséges összes infrastruktúrát, akár manuálisan, akár automatikusan.

Ennek ellenére néhány konkrét felhasználási esetben célszerű statikus gyári módszereket igénybe venni ugyanazon eredmény elérése érdekében.

Ebben az oktatóanyagban kiemeljük a A statikus gyári módszerek előnyei és hátrányai a sima régi Java konstruktorokkal szemben.

2. A statikus gyári módszerek előnyei a kivitelezőkkel szemben

Mi lehet a baj a konstruktorokkal egy olyan objektum-orientált nyelvben, mint a Java? Összességében semmi. Ennek ellenére a híres Joshua Block hatékony Java 1. pontja egyértelműen kimondja:

"Fontolja meg a statikus gyári módszereket a kivitelezők helyett"

Bár ez nem ezüst golyó, itt vannak a legmeggyőzőbb okok, amelyek fenntartják ezt a megközelítést:

  1. A kivitelezőknek nincs értelmes nevük, ezért mindig a nyelv által előírt szabványos elnevezési szokásokra korlátozódnak. A statikus gyári módszereknek értelmes nevük lehet, így kifejezetten közvetítik, amit csinálnak
  2. A statikus gyári módszerek ugyanazt a típust adhatják vissza, amely megvalósítja a módszert (módszereket), egy altípust és primitíveket is, így rugalmasabb visszatérő típusokat kínálnak
  3. A statikus gyári módszerek be tudják foglalni az összes logikát, amely a teljesen inicializált példányok előkészítéséhez szükséges, így felhasználhatók a további logika kivitelezőkből történő elmozdítására. Ez megakadályozza, hogy a kivitelezők további feladatokat hajtsanak végre, mások mellett, csak a mezők inicializálása
  4. A statikus gyári módszerek vezérelhető-példányos módszerek, a Singleton minta a legszembetűnőbb példa erre a szolgáltatásra

3. Statikus gyári módszerek a JDK-ban

Rengeteg példa van a JDK statikus gyári módszereire, amelyek bemutatják a fent vázolt számos előnyt. Fedezzük fel néhányukat.

3.1. A Húr Osztály

A közismert miatt Húr internálás, nagyon valószínűtlen, hogy használni fogjuk a Húr osztály konstruktőre egy új létrehozásához Húr tárgy. Ennek ellenére ez teljesen legális:

Karakterlánc értéke = új karakterlánc ("Baeldung");

Ebben az esetben a konstruktor újat hoz létre Húr objektum, ami a várható viselkedés.

Alternatív megoldásként, ha akarjuk újat csinálni Húr objektumot statikus gyári módszerrel, használhatjuk a értéke() módszer:

String value1 = String.valueOf (1); String value2 = String.valueOf (1,0 L); String value3 = String.valueOf (true); String value4 = String.valueOf ('a'); 

Számos túlterhelt implementáció létezik értéke(). Mindegyik újat ad vissza Húr objektum, a metódushoz továbbított argumentum típusától függően (pl. int, hosszú, logikai, char, és így tovább).

A név elég világosan kifejezi, hogy mit csinál a módszer. A statikus gyári módszerek elnevezéséhez ragaszkodik a Java ökoszisztéma jól bevált szabványához is.

3.2. A Választható Osztály

A JDK statikus gyári módszereinek másik szép példája a Választható osztály. Ez az osztály néhány gyári módszert valósít meg elég értelmes nevekkel, beleértve üres(), nak,-nek(), és ofNullable ():

Opcionális érték1 = Opcionális. Üres (); Opcionális érték2 = Opcionális.of ("Baeldung"); Opcionális érték3 = Opcionális.Nullable (null);

3.3. A Gyűjtemények Osztály

Valószínűleg a statikus gyári módszerek legreprezentatívabb példája a JDK-ban a Gyűjtemények osztály. Ez egy nem azonnal osztályozható osztály, amely csak statikus módszereket valósít meg.

Ezek közül sok olyan gyári módszer, amelyek szintén visszaadják a gyűjteményeket, miután valamilyen típusú algoritmust alkalmaznak a szállított gyűjteményre.

Íme néhány tipikus példa az osztály gyári módszereire:

Gyűjtemény syncedCollection = Gyűjtemények.synchronizedCollection (originalCollection); Set syncedSet = Collections.synchronizedSet (új HashSet ()); List unmodifiableList = Collections.unmodifiableList (originalList); Map unmodifiableMap = Collections.unmodifiableMap (originalMap); 

A statikus gyári módszerek száma a JDK-ban nagyon nagy, ezért a rövidség kedvéért rövid példákat tartunk.

Mindazonáltal a fenti példáknak világos képet kell adniuk arról, hogy a statikus gyári módszerek mennyire vannak a Java-ban.

4. Egyedi statikus gyári módszerek

Természetesen, megvalósíthatjuk saját statikus gyári módszereinket. De mikor érdemes ezt megtenni, ahelyett, hogy egyszerű konstruktorokon keresztül osztálypéldányokat hoznánk létre?

Lássunk egy egyszerű példát.

Vegyük ezt naivnak Felhasználó osztály:

public class Felhasználó {private final String name; privát végleges karakterlánc e-mail; zártkörű vonós ország; public User (karakterlánc neve, karakterlánc e-mail, karakterlánc országa) {this.name = név; this.email = e-mail; ez.ország = ország; } // standard getters / toString}

Ebben az esetben nincsenek látható figyelmeztetések arra utalva, hogy a statikus gyári módszer jobb lehet, mint a szokásos konstruktor.

Mi van, ha ezt akarjuk Felhasználó példányok alapértelmezett értéket kapnak a ország terület?

Ha a mezőt alapértelmezett értékkel inicializáljuk, akkor a konstruktort is át kell alakítanunk, ezáltal a terv merevebbé válik.

Használhatunk helyette statikus gyári módszert:

public static Felhasználó createWithDefaultCountry (karakterlánc neve, karakterlánc e-mail) {return new User (név, e-mail, "Argentína"); }

Így kapjuk meg a Felhasználó példány, amelynek alapértelmezett értéke a ország terület:

Felhasználói felhasználó = User.createWithDefaultCountry ("John", "[email protected]");

5. A logika elmozdítása a kivitelezőkből

A mi Felhasználó osztály gyorsan hibás kialakítássá válhat, ha úgy döntünk, hogy olyan funkciókat valósítunk meg, amelyek további logikát igényelnek a kivitelező számára (a riasztó harangoknak ekkorra már megszólalnak).

Tegyük fel, hogy meg akarjuk adni az osztálynak azt a lehetőséget, hogy naplózza azt az időpontot, amikor minden Felhasználó objektum jön létre.

Ha csak beépítjük ezt a logikát a konstruktorba, akkor megtörnénk az egységes felelősség elvét. Egy monolit konstruktorral végzünk, amely sokkal többet tesz, mint a mezők inicializálása.

Statikus gyári módszerrel tisztán tudjuk tartani a tervezésünket:

public class Felhasználó {private static final Logger LOGGER = Logger.getLogger (User.class.getName ()); privát végleges karakterlánc neve; privát végleges karakterlánc e-mail; zártkörű vonós ország; // standard konstruktorok / getters public static Felhasználó createWithLoggedInstantiationTime (Karakterlánc neve, Karakterlánc e-mail, Karakterlánc országa) {LOGGER.log (Level.INFO, "Felhasználói példány létrehozása itt: {0}", LocalTime.now ()); új felhasználó visszaküldése (név, e-mail cím, ország); }} 

Így hozhatnánk létre továbbfejlesztett termékeinket Felhasználó példa:

Felhasználói felhasználó = User.createWithLoggedInstantiationTime ("John", "[email protected]", "Argentina");

6. Példány által irányított azonnali beavatkozás

Amint a fentiekből látható, a teljesen inicializált visszatérés előtt a logika darabjait statikus gyári módszerekbe foglalhatjuk Felhasználó tárgyakat. És ezt megtehetjük anélkül, hogy a kivitelezőt több, egymással nem összefüggő feladat elvégzésének felelősségével szennyeznénk.

Például, tegyük fel, hogy szeretnénk magunkévá tenni Felhasználó osztály egy Singleton. Ezt egy példányvezérelt statikus gyári módszer megvalósításával érhetjük el:

public class Felhasználó {private static volatile Felhasználói példány = null; // egyéb mezők / standard konstruktorok / getters public static Felhasználó getSingletonInstance (karakterlánc neve, karakterlánc e-mail, karakterlánc országa) {if (instance == null) {synchronized (User.class) {if (instance == null) {instance = new Felhasználó (név, e-mail, ország); }}} visszatérési példány; }} 

A getSingletonInstance () módszer az menetes, kis teljesítménybüntetéssel, a szinkronizált blokk miatt.

Ebben az esetben lusta inicializálást alkalmaztunk egy példányvezérelt statikus gyári módszer megvalósításának bemutatására.

Érdemes azonban megemlíteni azt a Singleton megvalósításának legjobb módja a Java enum típusú, mivel egyszerre biztonságos a szériaszám és a szál. A Singletons különböző megközelítésekkel történő megvalósításával kapcsolatos részletekért tekintse meg ezt a cikket.

A várakozásoknak megfelelően a Felhasználó Az objektum ezzel a módszerrel nagyon hasonlít az előző példákra:

Felhasználói felhasználó = User.getSingletonInstance ("John", "[email protected]", "Argentina");

7. Következtetés

Ebben a cikkben néhány olyan esetet tártunk fel, ahol a statikus gyári módszerek jobb alternatívát jelenthetnek a sima Java konstruktorok helyett.

Sőt, ez a visszafogási mintázat annyira szorosan gyökerezik egy tipikus munkafolyamatban, hogy a legtöbb IDE megteszi helyettünk.

Természetesen az Apache NetBeans, az IntelliJ IDEA és az Eclipse kissé eltérő módon végzi a refaktorálást, ezért kérjük, először ellenőrizze az IDE dokumentációját.

Mint sok más refaktorálási mintánál, a statikus gyári módszereket is kellő körültekintéssel kell használnunk, és csak akkor, ha érdemes kompromisszumot kötni a rugalmasabb és letisztultabb kialakítás és a további módszerek megvalósításának költségei között.

Szokás szerint a cikkben bemutatott összes kódminta elérhető a GitHubon.