CodeGym/Java blog/Véletlen/Tervezési minták: Absztrakt gyár
John Squirrels
Szint
San Francisco

Tervezési minták: Absztrakt gyár

Megjelent a csoportban
Szia! Ma folytatjuk a tervezési minták tanulmányozását, és megvitatjuk az absztrakt gyári mintát. Tervezési minták: Absztrakt gyár - 1A következőkkel foglalkozunk a leckében:
  • Megbeszéljük, mi az absztrakt gyár, és milyen problémát old meg ez a minta
  • Elkészítjük egy többplatformos alkalmazás vázát a kávé rendeléséhez felhasználói felületen keresztül
  • Tanulmányozzuk a minta használatára vonatkozó utasításokat, beleértve a diagram és a kód megtekintését
  • És bónuszként ez a lecke tartalmaz egy rejtett húsvéti tojást, amely segít megtanulni, hogyan kell a Java használatával meghatározni az operációs rendszer nevét, és az eredménytől függően végrehajtani egy-egy műveletet.
Ennek a mintának a teljes megértéséhez jártasnak kell lennie a következő témákban:
  • öröklődés Java nyelven
  • absztrakt osztályok és metódusok a Java nyelven

Milyen problémákat old meg egy absztrakt gyár?

Az absztrakt gyár, mint minden gyári minta, segít abban, hogy az új objektumok helyesen jöjjenek létre. Különböző egymáshoz kapcsolódó objektumcsaládok "gyártásának" kezelésére használjuk. Összekapcsolt objektumok különféle családjai... Mit jelent ez? Ne aggódjon: a gyakorlatban minden egyszerűbb, mint amilyennek látszik. Először is mi lehet az egymással összefüggő tárgyak családja? Tegyük fel, hogy katonai stratégiát dolgozunk ki, amely többféle egységre vonatkozik:
  • gyalogság
  • lovasság
  • íjászok
Az ilyen típusú egységek összefüggenek egymással, mivel ugyanabban a hadseregben szolgálnak. Mondhatnánk, hogy a fent felsorolt ​​kategóriák egymással összefüggő objektumok családját alkotják. Ezt megértjük. Az absztrakt gyári mintát azonban az egymással összekapcsolt objektumok különféle családjainak létrehozására használják. Itt sincs semmi bonyolult. Folytassuk a katonai stratégiai példával. Általánosságban elmondható, hogy a katonai egységek több különböző harcoló félhez tartoznak. Attól függően, hogy kinek az oldalán állnak, a katonai egységek megjelenése jelentősen eltérhet. A római hadsereg gyalogosai, lovasai és íjászai nem azonosak a viking gyalogosokkal, lovasokkal és íjászokkal. A katonai stratégiában a különböző hadseregek katonái egymással összefüggő objektumok különböző családjai. Vicces lenne, ha egy programozó s tévedése miatt a római gyalogság sorai között találtak egy katonát Napóleon-kori francia egyenruhában, muskétával készenlétben. Az absztrakt gyári tervezési mintára pontosan ennek a problémának a megoldásához van szükség. Nem, nem az időutazásból fakadó zavar, hanem az egymással összefüggő tárgyak különféle csoportjainak létrehozásának problémája. Egy absztrakt gyár felületet biztosít az összes elérhető termék (egy objektumcsalád) létrehozásához. Egy absztrakt gyárnak általában több megvalósítása van. Mindegyikük felelős az egyik család termékeinek létrehozásáért. Katonai stratégiánk egy absztrakt gyárat tartalmazna, amely absztrakt gyalogosokat, íjászokat és lovasokat hoz létre, valamint ennek a gyárnak a megvalósításait. Például, egy gyár, amely római légiósokat hoz létre, és egy gyár, amely karthágói katonákat hoz létre. Az absztrakció ennek a mintának a legfontosabb vezérelve. A gyár ügyfelei csak absztrakt felületeken keresztül dolgoznak a gyárral és annak termékeivel. Ebből kifolyólag nem kell azon gondolkodni, hogy éppen mely katonák készülnek. Ehelyett áthárítja ezt a felelősséget az absztrakt gyár valamilyen konkrét megvalósítására.

Folytassuk kávézónk automatizálását

Az utolsó leckében, a gyári módszermintát tanulmányoztuk. Kávé üzletünk bővítésére és több új helyszín megnyitására használtuk fel. Ma folytatjuk üzletünk modernizálását. Az absztrakt gyári mintát használva lefektetjük egy új, online kávérendelési asztali alkalmazás alapjait. Asztali alkalmazás írásakor mindig gondoljunk a platformok közötti támogatásra. Alkalmazásunknak működnie kell macOS és Windows rendszeren is (spoiler: A Linux támogatását házi feladatként kell megvalósítania). Hogyan fog kinézni az alkalmazásunk? Elég egyszerű: ez egy szövegmezőből, kijelölőmezőből és gombból álló űrlap lesz. Ha van tapasztalata különböző operációs rendszerek használatában, biztosan észrevette, hogy a Windows gombjai másképp jelennek meg, mint a Mac-en. Ahogy minden más... Nos, kezdjük.
  • gombokat
  • szöveges mezőket
  • kiválasztási mezőket
Felelősség kizárása: Minden felületen meghatározhatunk metódusokat, például onClick, onValueChanged, vagy onInputChanged. Vagyis definiálhatnánk olyan metódusokat, amelyek segítségével különféle eseményeket kezelhetünk (gomb megnyomása, szöveg bevitele, érték kijelölése egy kijelölőmezőben). Mindezt szándékosan kihagytuk itt, hogy ne terheljük túl a példát, és hogy a gyári minta tanulmányozása során világosabb legyen. Határozzuk meg termékeink absztrakt felületeit:
public interface Button {}
public interface Select {}
public interface TextField {}
Minden operációs rendszerhez interfész elemeket kell létrehoznunk az operációs rendszer stílusában. Kódot fogunk írni Windows és MacOS számára. Hozzuk létre a Windows implementációit:
public class WindowsButton implements Button {
}

public class WindowsSelect implements Select {
}

public class WindowsTextField implements TextField {
}
Most ugyanezt tesszük MacOS esetén:
public class MacButton implements Button {
}

public class MacSelect implements Select {
}

public class MacTextField implements TextField {
}
Kiváló. Most továbbléphetünk absztrakt gyárunkba, amely létrehozza az összes elérhető absztrakt terméktípust:
public interface GUIFactory {

    Button createButton();
    TextField createTextField();
    Select createSelect();

}
Nagyszerű. Mint látható, még nem csináltunk semmi bonyolultat. Minden, ami ezután következik, szintén egyszerű. A termékekhez hasonlóan különféle gyári implementációkat készítünk minden operációs rendszerhez. Kezdjük a Windows rendszerrel:
public class WindowsGUIFactory implements GUIFactory {
    public WindowsGUIFactory() {
        System.out.println("Creating GUIFactory for Windows OS");
    }

    public Button createButton() {
        System.out.println("Creating Button for Windows OS");
        return new WindowsButton();
    }

    public TextField createTextField() {
        System.out.println("Creating TextField for Windows OS");
        return new WindowsTextField();
    }

    public Select createSelect() {
        System.out.println("Creating Select for Windows OS");
        return new WindowsSelect();
    }
}
Hozzáadtunk néhány konzolkimenetet a metódusokhoz és a konstruktorhoz, hogy jobban illusztráljuk, mi történik. Most a macOS-hez:
public class MacGUIFactory implements GUIFactory {
    public MacGUIFactory() {
        System.out.println("Creating GUIFactory for macOS");
    }

    @Override
    public Button createButton() {
        System.out.println("Creating Button for macOS");
        return new MacButton();
    }

    @Override
    public TextField createTextField() {
        System.out.println("Creating TextField for macOS");
        return new MacTextField();
    }

    @Override
    public Select createSelect() {
        System.out.println("Creating Select for macOS");
        return new MacSelect();
    }
}
Vegye figyelembe, hogy minden metódusaláírás azt jelzi, hogy a metódus absztrakt típust ad vissza. A módszereken belül azonban a termékek konkrét megvalósításait hozzuk létre. Ez az egyetlen hely, ahol szabályozzuk az egyes példányok létrehozását. Itt az ideje, hogy osztályt írjunk az űrlaphoz. Ez egy Java osztály, amelynek mezői interfész elemek:
public class CoffeeOrderForm {
    private final TextField customerNameTextField;
    private final Select coffeeTypeSelect;
    private final Button orderButton;

    public CoffeeOrderForm(GUIFactory factory) {
        System.out.println("Creating coffee order form");
        customerNameTextField = factory.createTextField();
        coffeeTypeSelect = factory.createSelect();
        orderButton = factory.createButton();
    }
}
Az interfész elemeket létrehozó absztrakt gyár átadásra kerül az űrlap konstruktorának. A szükséges gyári megvalósítást átadjuk a konstruktornak, hogy interfész elemeket hozzon létre egy adott operációs rendszerhez.
public class Application {
    private CoffeeOrderForm coffeeOrderForm;

    public void drawCoffeeOrderForm() {
        // Determine the name of the operating system through System.getProperty()
        String osName = System.getProperty("os.name").toLowerCase();
        GUIFactory guiFactory;

        if (osName.startsWith("win")) { // For Windows
            guiFactory = new WindowsGUIFactory();
        } else if (osName.startsWith("mac")) { // For Mac
            guiFactory = new MacGUIFactory();
        } else {
            System.out.println("Unknown OS. Unable to draw form :(");
            return;
        }
        coffeeOrderForm = new CoffeeOrderForm(guiFactory);
    }

    public static void main(String[] args) {
        Application application = new Application();
        application.drawCoffeeOrderForm();
    }
}
Ha az alkalmazást Windowson futtatjuk, a következő kimenetet kapjuk:
Creating GUIFactory for Windows OS
Creating coffee order form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
Macen a kimenet a következő lesz:
Creating GUIFactory for macOS
Creating coffee order form
Creating TextField for macOS
Creating Select for macOS
Creating Button for macOS
Linuxon:
Unknown OS. Unable to draw form :(
És most összefoglaljuk. Megírtuk egy grafikus felhasználói felület alapú alkalmazás vázát, amelyben az interfész elemei kifejezetten az adott operációs rendszerhez készültek. Röviden megismételjük, amit létrehoztunk:
  • Egy beviteli mezőből, egy kiválasztási mezőből és egy gombból álló termékcsalád.
  • A termékcsalád különböző megvalósításai Windows és macOS rendszerekhez.
  • Absztrakt gyár, amely interfészt határoz meg termékeink létrehozásához.
  • Üzemünk két megvalósítása, mindegyik egy-egy termékcsalád létrehozásáért felelős.
  • Űrlap (Java osztály), amelynek mezői absztrakt felületelemek, amelyeket a konstruktorban egy absztrakt gyár segítségével inicializálnak a szükséges értékekkel.
  • Alkalmazás osztály Ezen az osztályon belül létrehozunk egy űrlapot, átadva a kívánt gyári implementációt a konstruktorának.
A végeredmény az, hogy megvalósítottuk az absztrakt gyári mintát.

Absztrakt gyár: hogyan kell használni

Az absztrakt gyár olyan tervezési minta, amellyel különféle termékcsaládok létrehozását kezelhetjük anélkül, hogy konkrét termékosztályokhoz kötnénk. Ennek a mintának a használatakor a következőket kell tennie:
  1. Termékcsaládok meghatározása. Tegyük fel, hogy kettőnk van közülük:
    • SpecificProductA1,SpecificProductB1
    • SpecificProductA2,SpecificProductB2
  2. A családon belül minden termékhez határozzon meg egy absztrakt osztályt (interfészt). A mi esetünkben a következőkkel rendelkezünk:
    • ProductA
    • ProductB
  3. Minden termékcsaládon belül minden terméknek megvalósítania kell a 2. lépésben meghatározott interfészt.
  4. Hozzon létre egy absztrakt gyárat, a 2. lépésben meghatározott módszerekkel az egyes termékek létrehozásához. Esetünkben ezek a módszerek a következők:
    • ProductA createProductA();
    • ProductB createProductB();
  5. Hozzon létre absztrakt gyári implementációkat, hogy minden implementáció egyetlen család termékeinek létrehozását vezérelje. Ehhez az absztrakt gyár minden egyes megvalósításán belül meg kell valósítani az összes létrehozási metódust, hogy azok meghatározott termékmegvalósításokat hozzanak létre és adjanak vissza.
A következő UML diagram a fent vázolt utasításokat szemlélteti: Tervezési minták: Absztrakt gyár - 3Most a következő utasítások szerint írunk kódot:
// Define common product interfaces
public interface ProductA {}
public interface ProductB {}

// Create various implementations (families) of our products
public class SpecificProductA1 implements ProductA {}
public class SpecificProductB1 implements ProductB {}

public class SpecificProductA2 implements ProductA {}
public class SpecificProductB2 implements ProductB {}

// Create an abstract factory
public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

// Implement the abstract factory in order to create products in family 1
public class SpecificFactory1 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB1();
    }
}

// Implement the abstract factory in order to create products in family 2
public class SpecificFactory2 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB2();
    }
}

Házi feladat

Az anyag megerősítéséhez két dolgot tehet:
  1. Finomítsa a kávérendelő alkalmazást, hogy az Linuxon is működjön.
  2. Hozzon létre saját absztrakt gyárat bármilyen katonai stratégiában részt vevő egységek gyártásához. Ez lehet egy történelmi katonai stratégia valódi hadseregekkel, vagy egy képzeletbeli stratégia orkokkal, gnómokkal és elfekkel. A lényeg az, hogy olyat válassz, ami érdekel. Legyen kreatív, nyomtasson üzeneteket a konzolra, és élvezze a minták megismerését!
Hozzászólások
  • Népszerű
  • Új
  • Régi
Hozzászólás írásához be kell jelentkeznie
Ennek az oldalnak még nincsenek megjegyzései