CodeGym/Java blog/Véletlen/Tervezési minták: Gyári módszer
John Squirrels
Szint
San Francisco

Tervezési minták: Gyári módszer

Megjelent a csoportban
Szia! Ma folytatjuk a tervezési minták tanulmányozását, és megvitatjuk a gyári módszer mintáját. Tervezési minták: Gyári módszer - 1 Megtudhatja, mi ez, és milyen feladatokra alkalmas ez a minta. Ezt a tervezési mintát a gyakorlatban megvizsgáljuk, és megvizsgáljuk a szerkezetét. Annak érdekében, hogy minden világos legyen, meg kell értenie a következő témákat:
  1. Öröklés Java nyelven.
  2. Absztrakt metódusok és osztályok a Java nyelven

Milyen problémát old meg a gyári módszer?

Minden gyári tervezési mintának kétféle résztvevője van: alkotók (maguk a gyárak) és termékek (a gyárak által létrehozott tárgyak). Képzeljük el a következő helyzetet: van egy gyárunk, amely CodeGym márkájú autókat gyárt. Tudja, hogyan hozhat létre különféle karosszériájú autómodelleket:
  • szedánok
  • kombi kocsik
  • kupék
Vállalkozásunk annyira felvirágzott, hogy egy szép napon felvásároltunk egy másik autógyártót, a OneAuto-t. Értelmes cégtulajdonosok lévén nem akarunk elveszíteni egyetlen OneAuto ügyfelet sem, így a termelés átstrukturálása a feladat előtt áll, hogy előállíthassuk:
  • CodeGym szedánok
  • CodeGym kombi
  • CodeGym kupék
  • OneAuto szedánok
  • OneAuto kombi
  • OneAuto kupék
Mint látható, egy termékcsoport helyett most kettő van, és ezek bizonyos részletekben különböznek. A gyári módszer tervezési mintája arra az esetre szolgál, amikor különböző termékcsoportokat kell létrehoznunk, amelyek mindegyike rendelkezik bizonyos sajátosságokkal. Ennek a mintának a vezérelvét a gyakorlatban is figyelembe vesszük, fokozatosan haladva az egyszerűtől a bonyolult felé, az egyik előző leckében kialakított kávézónk példájával .

Egy kicsit a gyári mintáról

Hadd emlékeztesselek arra, hogy korábban építettünk egy kis virtuális kávézót. Egy egyszerű gyár segítségével megtanultuk, hogyan készítsünk különböző kávéfajtákat. Ma ezt a példát dolgozzuk át. Emlékezzünk vissza, hogyan nézett ki kávézónk, egyszerű gyárával. Kávéórát tartottunk:
public class Coffee {
    public void grindCoffee(){
        // Grind the coffee
    }
    public void makeCoffee(){
        // Brew the coffee
    }
    public void pourIntoCup(){
        // Pour into a cup
    }
}
És számos gyermekosztály, amelyek megfelelnek a gyárunk által gyártott kávéfajtáknak:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Létrehoztunk egy listát, hogy megkönnyítsük a rendeléseket:
public enum CoffeeType {
    ESPRESSO,
    AMERICANO,
    CAFFE_LATTE,
    CAPPUCCINO
}
Maga a kávégyár így nézett ki:
public class SimpleCoffeeFactory {
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new Americano();
                break;
            case ESPRESSO:
                coffee = new Espresso();
                break;
            case CAPPUCCINO:
                coffee = new Cappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new CaffeLatte();
                break;
        }

        return coffee;
    }
}
És végül maga a kávézó így nézett ki:
public class CoffeeShop {

    private final SimpleCoffeeFactory coffeeFactory;

    public CoffeeShop(SimpleCoffeeFactory coffeeFactory) {
        this.coffeeFactory = coffeeFactory;
    }

    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = coffeeFactory.createCoffee(type);
        coffee.grindCoffee();
        coffee.makeCoffee();
        coffee.pourIntoCup();

        System.out.println("Here's your coffee! Thanks! Come again!");
        return coffee;
    }
}

Egy egyszerű gyár korszerűsítése

A kávézónk nagyon jól működik. Olyannyira, hogy fontolgatjuk a bővítést. Néhány új helyszínt szeretnénk nyitni. Merészek és vállalkozó szelleműek vagyunk, így nem fogunk unalmas kávéházakat kirángatni. Azt akarjuk, hogy minden üzletben különleges fordulat legyen. Ennek megfelelően kezdetben két helyszínt nyitunk meg: egy olasz és egy amerikai. Ezek a változások nemcsak a belső kialakítást érintik, hanem a kínált italokat is:
  • az olasz kávézóban kizárólag olasz kávémárkákat használunk, speciális őrléssel és pörköléssel.
  • az amerikai helyszínen nagyobb adagok lesznek, és minden rendelésnél mályvacukrot szolgálunk fel.
Az egyetlen dolog, ami változatlan, az az üzleti modellünk, amely kiválónak bizonyult. Ami a kódot illeti, ez történik. 4 osztályunk volt a termékeinknek megfelelő:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
De most 8 lesz:
public class ItalianStyleAmericano extends Coffee {}
public class ItalianStyleCappucino extends Coffee {}
public class ItalianStyleCaffeLatte extends Coffee {}
public class ItalianStyleEspresso extends Coffee {}

public class AmericanStyleAmericano extends Coffee {}
public class AmericanStyleCappucino extends Coffee {}
public class AmericanStyleCaffeLatte extends Coffee {}
public class AmericanStyleEspresso extends Coffee {}
Mivel szeretnénk megtartani a jelenlegi üzleti modellt, szeretnénk, ha a orderCoffee(CoffeeType type)módszer a lehető legkevesebb változáson menne keresztül. Vessen egy pillantást rá:
public Coffee orderCoffee(CoffeeType type) {
    Coffee coffee = coffeeFactory.createCoffee(type);
    coffee.grindCoffee();
    coffee.makeCoffee();
    coffee.pourIntoCup();

    System.out.println("Here's your coffee! Thanks! Come again!");
    return coffee;
}
Milyen lehetőségeink vannak? Nos, már tudjuk, hogyan kell gyárat írni, igaz? A legegyszerűbb, ami rögtön eszünkbe jut, hogy írjunk két hasonló gyárat, majd adjuk át kávézónk kivitelezőjének a kívánt megvalósítást. Ezzel a kávézó osztálya nem változik. Először is létre kell hoznunk egy új gyári osztályt, örökölni kell az egyszerű gyárunkat, majd felül kell írni a createCoffee(CoffeeType type)metódust. Írjunk gyárakat az olasz stílusú kávé és az amerikai stílusú kávé előállításához:
public class SimpleItalianCoffeeFactory extends SimpleCoffeeFactory {

    @Override
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;
        switch (type) {
            case AMERICANO:
                coffee = new ItalianStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new ItalianStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new ItalianStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new ItalianStyleCaffeLatte();
                break;
        }
        return coffee;
    }
}

public class SimpleAmericanCoffeeFactory extends SimpleCoffeeFactory{

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new AmericanStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new AmericanStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new AmericanStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new AmericanStyleCaffeLatte();
                break;
        }

        return coffee;
    }

}
Most átadhatjuk a kívánt gyári megvalósítást a CoffeeShopnak. Nézzük meg, hogyan nézne ki a különböző kávézókból történő kávérendelés kódja. Például olasz és amerikai stílusú cappuccino:
public class Main {
    public static void main(String[] args) {
        /*
            Order an Italian-style cappuccino:
            1. Create a factory for making Italian coffee
            2. Create a new coffee shop, passing the Italian coffee factory to it through the constructor
            3. Order our coffee
         */
        SimpleItalianCoffeeFactory italianCoffeeFactory = new SimpleItalianCoffeeFactory();
        CoffeeShop italianCoffeeShop = new CoffeeShop(italianCoffeeFactory);
        italianCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);


         /*
            Order an American-style cappuccino
            1. Create a factory for making American coffee
            2. Create a new coffee shop, passing the American coffee factory to it through the constructor
            3. Order our coffee
         */
        SimpleAmericanCoffeeFactory americanCoffeeFactory = new SimpleAmericanCoffeeFactory();
        CoffeeShop americanCoffeeShop = new CoffeeShop(americanCoffeeFactory);
        americanCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
    }
}
Két különböző kávézót hoztunk létre, mindegyiknek átadva a kívánt gyárat. Egyrészt teljesítettük a célunkat, másrészt... Valahogy ez nem áll jól a vállalkozóknak... Találjuk ki, mi a baj. Először is a gyárak bősége. Mit? Most minden új helyszínhez saját gyárat kell létrehoznunk, és ezen felül ügyelnünk arra, hogy a kávézó létrehozásakor az érintett gyárat átadják a kivitelezőnek? Másodszor, ez még mindig egy egyszerű gyár. Csak kicsit modernizálva. De azért vagyunk itt, hogy megtanuljunk egy új mintát. Harmadszor, nem lehetséges más megközelítés? Jó lenne, ha a kávékészítéssel kapcsolatos összes kérdést bele tudnánk helyezniCoffeeShoposztályba a kávékészítési folyamatok és a rendelések kiszolgálásának összekapcsolásával, ugyanakkor megfelelő rugalmasság fenntartása a különböző stílusú kávék elkészítéséhez. A válasz igen, megtehetjük. Ezt gyári módszer tervezési mintának nevezik.

Az egyszerű gyáritól a gyári módszerig

A feladat lehető leghatékonyabb megoldása érdekében:
  1. Visszaadjuk a createCoffee(CoffeeType type)metódust az CoffeeShoposztálynak.
  2. Ezt a módszert absztrakttá tesszük.
  3. Maga az CoffeeShoposztály absztrakt lesz.
  4. Az CoffeeShoposztálynak gyerekórái lesznek.
Igen barátom. Az olasz kávézó nem más, mint annak az CoffeeShoposztálynak a leszármazottja, amely createCoffee(CoffeeType type)az olasz baristák legjobb hagyományainak megfelelően valósítja meg a módszert. Most lépésről lépésre. 1. lépés: Tegye Coffeeabsztrakttá az osztályt. Két különböző termékcsaládunk van. Ennek ellenére az olasz és az amerikai kávéknak van egy közös őse – az Coffeeosztály. Helyénvaló lenne elvonatkoztatni:
public abstract class Coffee {
    public void makeCoffee(){
        // Brew the coffee
    }
    public void pourIntoCup(){
        // Pour into a cup
    }
}
2. lépés: Készítsen CoffeeShopabsztraktot, absztrakt createCoffee(CoffeeType type)módszerrel
public abstract class CoffeeShop {

    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = createCoffee(type);

        coffee.makeCoffee();
        coffee.pourIntoCup();

        System.out.println("Here's your coffee! Thanks! Come again!");
        return coffee;
    }

    protected abstract Coffee createCoffee(CoffeeType type);
}
3. lépés: Hozzon létre egy olasz kávézót, amely az absztrakt kávézó leszármazottja. createCoffee(CoffeeType type)Az olasz receptek sajátosságait figyelembe véve valósítjuk meg benne a módszert.
public class ItalianCoffeeShop extends CoffeeShop {

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;
        switch (type) {
            case AMERICANO:
                coffee = new ItalianStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new ItalianStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new ItalianStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new ItalianStyleCaffeLatte();
                break;
        }
        return coffee;
    }
}
4. lépés Ugyanezt tesszük az amerikai stílusú kávézóval is
public class AmericanCoffeeShop extends CoffeeShop {
    @Override
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new AmericanStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new AmericanStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new AmericanStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new AmericanStyleCaffeLatte();
                break;
        }

        return coffee;
    }
}
5. lépés: Nézze meg, hogyan néz ki az amerikai és olasz tejeskávé:
public class Main {
    public static void main(String[] args) {
        CoffeeShop italianCoffeeShop = new ItalianCoffeeShop();
        italianCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);

        CoffeeShop americanCoffeeShop = new AmericanCoffeeShop();
        americanCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
    }
}
Gratulálunk. Az imént a gyári módszer szerinti tervezési mintát valósítottuk meg kávézónk példájával.

A gyári módszerek mögött rejlő elv

Most nézzük meg részletesebben, mit kaptunk. Az alábbi diagram az eredményül kapott osztályokat mutatja. A zöld blokkok alkotói osztályok, a kék blokkok pedig termékosztályok. Tervezési minták: Gyári módszer - 2Milyen következtetéseket vonhatunk le?
  1. Minden termék az absztrakt osztály megvalósítása Coffee.
  2. Minden alkotó az absztrakt osztály implementációja CoffeeShop.
  3. Két párhuzamos osztályhierarchiát látunk:
    • A termékek hierarchiája. Látunk olasz és amerikai leszármazottakat
    • Az alkotók hierarchiája. Látunk olasz és amerikai leszármazottakat
  4. A CoffeeShopszuperosztálynak nincs információja arról, hogy melyik termék ( Coffee) jön létre.
  5. A CoffeeShopszuperosztály egy adott termék létrehozását a leszármazottaira ruházza.
  6. Az osztály minden leszármazottja CoffeeShopegy createCoffee()gyári metódust valósít meg a saját jellemzőinek megfelelően. Vagyis a termelői osztályok implementációi a termelői osztály sajátosságai alapján konkrét termékeket készítenek.
Most már készen áll a gyári módszerminta meghatározására . A gyári metódusminta interfészt definiál egy objektum létrehozásához, de lehetővé teszi az alosztályok számára a létrehozott objektum osztályának kiválasztását. Így a gyári metódus egy példány létrehozását alosztályokra delegálja. Általánosságban elmondható, hogy a definíció emlékezete nem olyan fontos, mint annak megértése, hogyan működik az egész.

Gyári módszer felépítése

Tervezési minták: Gyári módszer - 3A fenti diagram a gyári módszer mintájának általános felépítését mutatja. Mi más fontos itt?
  1. A Creator osztály minden olyan metódust megvalósít, amely interakcióba lép a termékekkel, kivéve a gyári módszert.
  2. Az absztrakt factoryMethod()metódust az osztály összes leszármazottjának implementálnia kell Creator.
  3. Az ConcreteCreatorosztály megvalósítja a factoryMethod()metódust, amely közvetlenül létrehozza a terméket.
  4. Ez az osztály felelős bizonyos termékek létrehozásáért. Ez az egyetlen osztály, amely információkat tartalmaz ezen termékek létrehozásáról.
  5. Minden terméknek közös interfészt kell megvalósítania, azaz egy közös termékosztály leszármazottjának kell lennie. Erre azért van szükség, hogy a termékeket használó osztályok absztrakcióként, nem pedig konkrét megvalósításként működhessenek rajtuk.

Házi feladat

Ma elég sok munkát végeztünk és tanulmányoztuk a gyári módszer tervezési mintáját. Ideje megerősíteni az anyagot! 1. gyakorlat. Végezze el a munkát egy másik kávézó megnyitásához. Ez lehet egy angol vagy spanyol stílusú kávézó. Vagy akár űrhajó-stílusban. Adjon ételfestéket a kávéhoz, hogy ragyogjon, és a kávéja egyszerűen nem lesz ebből a világból! 2. gyakorlat Az utolsó leckében volt egy gyakorlatod, ahol létrehoztál egy virtuális sushi bárt vagy egy virtuális pizzériát. Most az a gyakorlatod, hogy ne állj egy helyben. Ma megtanultad, hogyan használhatod a gyári módszert az előnyödre. Itt az ideje, hogy felhasználd ezt a tudást és bővítsd saját vállalkozásod ;)
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