Bevezetés a kreatív tervezési mintákba

1. Bemutatkozás

A szoftvertervezésben a Tervezési minta ismert megoldást ír le a szoftvertervezés során leggyakrabban előforduló problémákra. Ez a tapasztalt szoftverfejlesztők által hosszú időn keresztül kialakított legjobb gyakorlatokat képviseli.

A Design Patterns a Design Patterns: Elusable Object-Oriented Software Elements című könyv 1994-ben jelent meg Erich Gamma, John Vlissides, Ralph Johnson és Richard Helm (más néven Négyes bandája vagy GoF) könyv megjelenése után.

Ebben a cikkben a kreatív tervezési mintákat és azok típusait tárjuk fel. Megvizsgálunk néhány kódmintát, és megvitatjuk azokat a helyzeteket, amikor ezek a minták megfelelnek a tervünknek.

2. Kreatív tervezési minták

A kreatív tervezési minták az objektumok létrehozásának módjával foglalkoznak. Csökkentik a bonyolultságot és az instabilitást azáltal, hogy objektumokat irányított módon hoznak létre.

A új operátor gyakran károsnak tekinthető, mivel szétszórja az objektumokat az alkalmazásban. Idővel kihívássá válhat a megvalósítás megváltoztatása, mivel az osztályok szorosan összekapcsolódnak.

A kreatív tervezési minták úgy kezelik ezt a problémát, hogy teljesen leválasztják az ügyfelet a tényleges inicializálási folyamatról.

Ebben a cikkben a Creational Design Pattern négy típusát tárgyaljuk:

  1. Singleton - Biztosítja, hogy egy alkalmazáson belül csak egy objektum létezzen
  2. Gyári módszer - Több kapcsolódó osztály objektumát hozza létre a létrehozandó objektum pontos meghatározása nélkül
  3. Absztrakt gyár - hozzák létre a kapcsolódó függő tárgyakat
  4. ÉpítészBonyolult objektumokat épít lépésről-lépésre

Most részletesen tárgyaljuk meg ezeket a mintákat.

3. Singleton Design Pattern

A Singleton Design Pattern célja, hogy ellenőrizze egy adott osztály objektumainak inicializálását annak biztosítása, hogy az objektumnak csak egy példánya létezzen a Java virtuális gépben.

A Singleton osztály egy egyedi globális hozzáférési pontot is biztosít az objektumhoz, így a hozzáférési pontra irányuló minden további hívás csak az adott objektumot adja vissza.

3.1. Singleton minta példa

Noha a GoF vezette be a Singleton mintát, az eredeti megvalósítás problémás a többszálas forgatókönyvekben.

Tehát itt egy optimálisabb megközelítést fogunk követni, amely a statikus belső osztályt használja:

nyilvános osztály Singleton {private Singleton () {} privát statikus osztály SingletonHolder {public static final Singleton instance = new Singleton (); } public static Singleton getInstance () {return SingletonHolder.instance; }}

Itt hoztuk létre a statikus belső osztály, amely a Szingli osztály. Csak akkor hozza létre a példányt, ha valaki felhívja a getInstance () módszer, és nem akkor, ha a külső osztály betöltődik.

Ez egy széles körben alkalmazott megközelítés a Singleton osztály számára, mivel nem igényel szinkronizálást, szálbiztos, lusta inicializálást hajt végre, és viszonylag kevesebb a kazánja.

Vegye figyelembe azt is, hogy a konstruktor rendelkezik a magán hozzáférés módosító. Ez a Singleton létrehozásának követelménye, mivel a nyilvános A konstruktor azt jelentené, hogy bárki hozzáférhet hozzá, és új példányokat hozhat létre.

Ne feledje, hogy ez nem az eredeti GoF megvalósítás. Az eredeti verzióért kérjük, olvassa el ezt a linkelt Baeldung cikket a Java Singletons-ről.

3.2. Mikor kell használni a Singleton tervezési mintát

  • Drága erőforrások létrehozása (például adatbázis-kapcsolat objektumok)
  • Jó gyakorlat, ha minden fakitermelőt Singletonként tartunk, ami növeli a teljesítményt
  • Osztályok, amelyek hozzáférést biztosítanak az alkalmazás konfigurációs beállításaihoz
  • Osztályok, amelyek erőforrásokat tartalmaznak, amelyekhez megosztott módban férnek hozzá

4. Gyári módszer tervezési mintája

A gyári tervezési minta vagy a gyári módszer tervezési mintája a Java egyik leggyakrabban használt tervezési mintája.

A GoF szerint ez a minta „Definiál egy felületet egy objektum létrehozásához, de hagyja, hogy az alosztályok döntsék el, melyik osztályt kell példányosítani. A Factory módszer lehetővé teszi, hogy az osztály elhalaszthassa az alosztályok példányosítását ”.

Ez a minta átruházza az osztály inicializálásának felelősségét az ügyféltől egy adott gyári osztályig egy virtuális konstruktor típusának létrehozásával.

Ennek eléréséhez egy olyan gyárra támaszkodunk, amely biztosítja az objektumokat, elrejtve a megvalósítás tényleges részleteit. A létrehozott objektumokat egy közös felületen lehet elérni.

4.1. Gyári módszer tervezési minta példa

Ebben a példában létrehozunk egy Poligon interfész, amelyet több konkrét osztály fog megvalósítani. A PolygonFactory a tárgyak ebből a családból történő lekérésére szolgál:

Először hozzuk létre a Poligon felület:

nyilvános felület Polygon {String getType (); }

Ezután létrehozunk néhány megvalósítást, például Négyzet, Háromszög, stb., amelyek megvalósítják ezt az interfészt és visszaadnak egy objektumot Poligon típus.

Most létrehozhatunk egy gyárat, amely az oldalak számát veszi figyelembe argumentumként, és visszaadja ennek az interfésznek a megfelelő megvalósítását:

public class PolygonFactory {public Polygon getPolygon (int numberOfSides) {if (numberOfSides == 3) {return new Triangle (); } if (numberOfSides == 4) {adja vissza az új négyzetet (); } if (numberOfSides == 5) {adja vissza az új Pentagonot (); } if (numberOfSides == 7) {adja vissza az új Heptagont (); } else if (numberOfSides == 8) {adja vissza az új nyolcszöget (); } return null; }}

Vegye figyelembe, hogy az ügyfél hogyan támaszkodhat erre a gyárra, hogy megfelelőt nyújtson nekünk Poligon, anélkül, hogy közvetlenül kellene inicializálni az objektumot.

4.2. Mikor kell használni a gyári módszer tervezési mintáját

  • Amikor egy interfész vagy egy absztrakt osztály megvalósítása várhatóan gyakran változik
  • Amikor a jelenlegi megvalósítás nem képes kényelmesen befogadni az új változásokat
  • Amikor az inicializálás viszonylag egyszerű, és a konstruktor csak néhány paramétert igényel

5. Absztrakt gyártervezési minta

Az előző szakaszban azt láttuk, hogy a Factory Method tervezési mintával miként lehet egyetlen családhoz kapcsolódó objektumokat létrehozni.

Ezzel szemben az absztrakt gyári tervezési mintát kapcsolódó vagy függő objektumok családjainak létrehozására használják. Néha gyárgyárnak is hívják.

Részletes magyarázatért tekintse meg az Abstract Factory oktatóanyagunkat.

6. Építő tervezési minta

A Builder Design Pattern egy másik kreatív minta, amelyet viszonylag összetett objektumok felépítésének kezelésére terveztek.

Amikor az objektum létrehozásának bonyolultsága növekszik, a Builder minta elkülönítheti a példányosítási folyamatot egy másik objektum (építő) felhasználásával az objektum létrehozásához.

Ezt az építőt ezután sok más hasonló ábrázolás létrehozására lehet használni, egyszerű, lépésről lépésre történő megközelítéssel.

6.1. Építőminta példa

A GoF által bevezetett eredeti Builder Design Pattern az absztrakcióra összpontosít, és nagyon jó komplex objektumok kezelésénél, azonban a tervezés kissé bonyolult.

Joshua Bloch Effective Java című könyvében bemutatta az építőminta továbbfejlesztett változatát, amely tiszta, jól olvasható (mivel kifogástalanul alkalmazza a tervezést) és az ügyfél szempontjából könnyen használható. Ebben a példában megvitatjuk ezt a verziót.

Ennek a példának csak egy osztálya van, Bankszámla amely építőt tartalmaz a-ként statikus belső osztály:

public class BankAccount {private String name; private String accountNumber; privát karakterlánc e-mail; saját logikai hírlevél; // constructors / getters public static class BankAccountBuilder {// builder code}} 

Vegye figyelembe, hogy a mezők összes hozzáférés-módosítója deklarálva van magán mivel nem akarjuk, hogy a külső tárgyak közvetlenül hozzáférjenek hozzájuk.

A kivitelező is magán hogy csak az ehhez az osztályhoz rendelt Builder férhessen hozzá. A konstruktorban beállított összes tulajdonság kivonásra kerül az építõ objektumból, amelyet argumentumként adunk meg.

Meghatároztuk BankAccountBuilder a statikus belső osztály:

public static class BankAccountBuilder {private String name; private String accountNumber; privát karakterlánc e-mail; saját logikai hírlevél; public BankAccountBuilder (karakterlánc neve, String számlaszám) {this.név = név; this.accountNumber = accountNumber; } public BankAccountBuilder withEmail (karakterlánc e-mail) {this.email = email; adja vissza ezt; } public BankAccountBuilder wantNewsletter (logikai hírlevél) {this.newsletter = hírlevél; adja vissza ezt; } public BankAccount build () {return new BankAccount (this); }} 

Figyelje meg, hogy ugyanazt a mezőkészletet deklaráltuk, amelyet a külső osztály tartalmaz. Minden kötelező mező kötelező argumentumként szolgál a belső osztály konstruktora számára, míg a többi opcionális mező a setter módszerekkel határozható meg.

Ez a megvalósítás támogatja a gördülékeny tervezési megközelítést azáltal, hogy a setter módszerekkel visszaküldi az építőobjektumot.

Végül a build metódus meghívja a külső osztály privát konstruktorát, és önmagát adja át argumentumként. A visszatért Bankszámla a. által beállított paraméterekkel lesz példányos BankAccountBuilder.

Lássunk egy gyors példát az építő mintára:

BankAccount newAccount = new BankAccount .BankAccountBuilder ("Jon", "22738022275") .withEmail ("[[e-mail védett]") .wantNewsletter (true) .build ();

6.2. Mikor kell használni a Builder Pattern-t

  1. Amikor egy objektum létrehozásával kapcsolatos folyamat rendkívül összetett, sok kötelező és opcionális paraméterrel
  2. Amikor a konstruktor paramétereinek számának növekedése a konstruktorok nagy listájához vezet
  3. Amikor az ügyfél különböző reprezentációkat vár a létrehozott objektumtól

7. Következtetés

Ebben a cikkben megismerkedtünk a Java kreatív tervezési mintáival. Megbeszéltük a négy különböző típusukat is, azaz a Singletont, a Gyári módszert, az Absztrakt gyárat és az Építőmintát, az előnyeiket, a példákat és azt, hogy mikor használjuk őket.

Mint mindig, a teljes kódrészletek elérhetők a GitHubon.