Hej ven! I dag vil vi fortsætte med at studere designmønstre. I denne lektion skal vi tale om fabrikker. Vi vil diskutere det problem, som dette mønster løser, og se på et eksempel på, hvordan en fabrik kan hjælpe dig med at åbne en kaffebar. Derudover vil jeg give dig 5 enkle trin til at oprette en fabrik. Fabriksdesignmønster - 1 For at sikre, at vi alle er på samme bølgelængde, og at du hurtigt forstår dette koncept, bør du være bekendt med følgende emner:
  • Arv i Java
  • Indsnævring og udvidelse af referencetyper i Java
  • Interaktion mellem forskellige klasser og objekter.

Hvad er en fabrik?

Fabriksdesignmønsteret giver dig mulighed for at kontrollere oprettelsen af ​​objekter. Processen med at skabe et nyt objekt er ikke super simpel, men den er heller ikke alt for kompliceret. Vi ved alle, at vi har brug for operatøren newtil at skabe et nyt objekt. Måske ser det ud til, at der ikke er noget at kontrollere her, men det er ikke sandt. Antag, at vores applikation har en bestemt klasse, der har mange efterkommere. Der kan opstå vanskeligheder, når det er nødvendigt at oprette en instans af en specifik klasse afhængigt af visse forhold. En fabrik er et designmønster, der hjælper med at løse problemet med at skabe forskellige objekter afhængigt af visse forhold. Hvordan er det for et abstrakt koncept? Dette bliver tydeligere og mere specifikt, når vi ser på eksemplet nedenfor.

Lad os tilberede forskellige typer kaffe

Antag, at vi vil automatisere en kaffebar. Vi skal lære vores program at lave forskellige typer kaffe. For at gøre dette vil vi oprette en kaffeklasse og et par afledte klasser for at repræsentere de typer kaffe, vi vil tilberede: Americano, cappuccino, espresso og latte. Lad os starte med en generel kaffetime:

public class Coffee {
    public void grindCoffee(){
        // Grind the coffee
    }
    public void makeCoffee(){
        // Brew the coffee
    }
    public void pourIntoCup(){
        // Pour into a cup
    }
}
Dernæst opretter vi dens børneklasser:

public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Vores kunder kan bestille enhver type kaffe. Deres ordrer skal videregives til programmet. Dette kan gøres på mange måder, for eksempel ved hjælp af String. Men en enumer bedst til dette. Vi opretter enumog definerer enum-felter, der svarer til de kaffetyper, der kan bestilles:

public enum CoffeeType {
    ESPRESSO,
    AMERICANO,
    CAFFE_LATTE,
    CAPPUCCINO
}
Store. Lad os nu skrive koden til vores kaffebar:

public class CoffeeShop {
    
    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = null;
        
        switch (type) {
            case AMERICANO:
                coffee = new Americano();
                break;
            case ESPRESSO:
                coffee = new Espresso();
                break;
            case CAPPUCCINO:
                coffee = new Cappucсino();
                break;
            case CAFFE_LATTE:
                coffee = new CaffeLatte();
                break;
        }

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

        System.out.println("Here's your coffee! Thanks! Come again!");
        return coffee;
    }
}
Metoden orderCoffeekan opdeles i to dele:
  1. Oprettelse af en specifik forekomst af kaffe i en switcherklæring. Det er her, en fabrik gør, hvad den gør - skaber en bestemt type afhængigt af forholdene.
  2. Forberedelse - dette er maling, brygning og hældning i en kop.
Her er det, der er vigtigt at vide, hvis du skal foretage ændringer i metoden i fremtiden:
  1. De trin, der er involveret i selve tilberedningen (slibning, brygning og hældning i en kop) forbliver uændrede (i det mindste regner vi med dette).
  2. Men udvalget af kaffe kan ændre sig. Måske begynder vi at lave mokka... Frappu... Mochacci... Uanset hvad, en ny slags kaffe.
Vi kan allerede nu være ret sikre på, at vi i fremtiden skal lave ændringer i metodens switchredegørelse. Det er også muligt, at metoden i vores kaffebar orderCoffeeikke vil være det eneste sted, hvor vi vil skabe forskellige typer kaffe. Som følge heraf skal der foretages ændringer flere steder. Du forstår sikkert allerede, hvad jeg går efter. Vi er nødt til at refaktorere. Flyt blokken, der er ansvarlig for at lave kaffe, til en separat klasse af to årsager:
  1. Vi kan genbruge kaffemagerlogikken andre steder.
  2. Hvis sortimentet ændres, behøver vi ikke at redigere koden overalt, hvor kaffen bliver til. Det vil være nok at ændre vores kode ét sted.
Tiden er med andre ord inde til at etablere en fabrik.

Opsætning af vores første fabrik

For at gøre dette opretter vi en ny klasse, der kun vil være ansvarlig for at oprette de nødvendige forekomster af kaffeklasser:

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 Cappucino();
                break;
            case CAFFE_LATTE:
                coffee = new CaffeLatte();
                break;
        }
        
        return coffee;
    }
}
Tillykke! Vi har netop implementeret fabriksdesignmønsteret i sin enkleste form (næsten). Det kunne have været endnu enklere, hvis vi gjorde createCoffeemetoden statisk. Men så ville vi miste to muligheder:
  1. Evnen til at arve SimpleCoffeeFactoryog tilsidesætte createCoffeemetoden.
  2. Evnen til at tilføje den nødvendige fabriksimplementering til vores klasser.
Forresten, apropos implementering... Vi skal tilbage til kaffebaren og tilføje vores kaffefabrik.

Tilføjelse af en fabrik til kaffebaren

Lad os omskrive kaffebar-klassen ved hjælp af en fabrik:

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;
    }
}
Fremragende. Nu vil vi give en kortfattet beskrivelse af den generelle struktur af fabriksdesignmønsteret.

5 trin til at åbne din egen fabrik

Trin 1. Dit program har en klasse med flere efterkommere, som i diagrammet nedenfor: Fabriksdesignmønster - 2Trin 2. Du opretter et enummed et felt for hver underordnede klasse:

    enum CatType {
        LION,
        TIGER,
        FLUFFY
    }
Trin 3. Byg din fabrik. Kald det CatFactory. Her er koden:

class CatFactory {}
Trin 4. På din fabrik skal du oprette en createCatmetode, der tager et CatTypeargument. Her er koden:

    class CatFactory {
        public Cat createCat(CatType type) {
            
        }
    }
Trin 5. I metodens brødtekst skal du skrive en switcherklæring, der opregner enum-felterne og opretter en forekomst af klassen, der svarer til den beståede enumværdi:

class CatFactory {
        public Cat createCat(CatType type) {
            Cat cat = null;
            
            switch (type) {
                case LION:
                    cat =  new Fluffy();
                    break;
                case TIGER:
                    cat = new Tiger();
                    break;
                case FLUFFY:
                    cat =  new Lion();
                    break;
            }
            
            return cat;
        }
    }
Nu kan du drive en fabrik som en chef. :)

Hvordan man øver sig

At læse er godt, at skrive kode er endnu bedre. Hvis dit navn har et lige antal bogstaver, kan du prøve at oprette dit eget virtuelle pizzeria. Hvis dit navn har et ulige antal bogstaver, kan du prøve at oprette en virtuel sushibar. Hvis du ikke har noget navn, var du heldig. I dag kan du slappe af.