Hallo vriend! Vandaag gaan we verder met het bestuderen van ontwerppatronen. In deze les gaan we het hebben over fabrieken. We bespreken het probleem dat dit patroon oplost en kijken naar een voorbeeld van hoe een fabriek je kan helpen bij het openen van een coffeeshop. Daarnaast geef ik je 5 eenvoudige stappen om een fabriek te maken. Om ervoor te zorgen dat we allemaal op dezelfde golflengte zitten en dat je dit concept snel begrijpt, moet je bekend zijn met de volgende onderwerpen:
- Overerving op Java
- Versmallen en verbreden van referentietypes in Java
- Interactie tussen verschillende klassen en objecten.
Wat is een fabriek?
Met het fabrieksontwerppatroon kunt u het maken van objecten regelen. Het proces van het maken van een nieuw object is niet supereenvoudig, maar ook niet overdreven ingewikkeld. We weten allemaal dat we denew
operator nodig hebben om een nieuw object te maken. Misschien lijkt het alsof er hier niets te controleren valt, maar dat is niet waar. Stel dat onze applicatie een bepaalde klasse heeft die veel afstammelingen heeft. Moeilijkheden kunnen optreden wanneer het nodig is om een instantie van een specifieke klasse te maken, afhankelijk van bepaalde voorwaarden. Een fabriek is een ontwerppatroon dat helpt bij het oplossen van het probleem van het maken van verschillende objecten, afhankelijk van bepaalde omstandigheden. Hoe is dat voor een abstract concept? Dit wordt duidelijker en specifieker als we naar het onderstaande voorbeeld kijken.
Laten we verschillende soorten koffie bereiden
Stel dat we een coffeeshop willen automatiseren. We moeten ons programma leren hoe we verschillende soorten koffie kunnen zetten. Om dit te doen, maken we een koffieklasse en enkele afgeleide klassen om de soorten koffie weer te geven die we gaan bereiden: Americano, cappuccino, espresso en latte. Laten we beginnen met een algemene koffieles:
public class Coffee {
public void grindCoffee(){
// Grind the coffee
}
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
Vervolgens maken we de onderliggende klassen:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Onze klanten kunnen elk type koffie bestellen. Hun opdrachten moeten worden doorgegeven aan het programma. Dit kan op vele manieren, bijvoorbeeld met behulp van String
. Maar een enum
is hiervoor het beste. We maken een enum
en definiëren opsommingsvelden die overeenkomen met de soorten koffie die kunnen worden besteld:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
Geweldig. Laten we nu de code voor onze coffeeshop schrijven:
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;
}
}
De orderCoffee
methode kan in twee delen worden verdeeld:
- Creatie van een specifiek exemplaar van koffie in een
switch
verklaring. Dit is waar een fabriek doet wat het doet: een specifiek type maken, afhankelijk van de omstandigheden. - Voorbereiding - dit is het malen, brouwen en in een kopje gieten.
- De stappen van de bereiding zelf (malen, brouwen en in een kopje gieten) blijven ongewijzigd (daar rekenen we tenminste op).
- Maar het assortiment koffies kan veranderen. Misschien gaan we mokka maken... Frappu... Mochacci... Wat dan ook, een nieuwe soort koffie.
switch
verklaring van de methode. Het kan ook zijn dat in onze coffeeshop de orderCoffee
methode niet de enige plek is waar we verschillende soorten koffie gaan maken. Hierdoor zullen op meerdere plaatsen wijzigingen moeten worden doorgevoerd. U begrijpt waarschijnlijk al waar ik op doel. We moeten refactoren. Verplaats het blok dat verantwoordelijk is voor het maken van koffie naar een aparte klasse om twee redenen:
- De logica van het koffiezetten kunnen we op andere plekken hergebruiken.
- Als het assortiment verandert, hoeven we niet overal waar koffie wordt gemaakt de code te bewerken. Het is voldoende om onze code op slechts één plek te wijzigen.
Het opzetten van onze eerste fabriek
Om dit te doen, maken we een nieuwe klasse die alleen verantwoordelijk is voor het maken van de noodzakelijke exemplaren van koffieklassen:
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;
}
}
Gefeliciteerd! We hebben zojuist het fabrieksontwerppatroon in zijn eenvoudigste vorm (bijna) geïmplementeerd. Het had nog eenvoudiger kunnen zijn als we de createCoffee
methode statisch hadden gemaakt. Maar dan zouden we twee mogelijkheden verliezen:
- De mogelijkheid om
SimpleCoffeeFactory
de methode over te nemen en te overschrijvencreateCoffee
. - De mogelijkheid om de vereiste fabrieksimplementatie aan onze lessen toe te voegen.
Een fabriek toevoegen aan de coffeeshop
Laten we de coffeeshopklasse herschrijven met behulp van een fabriek:
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;
}
}
Uitstekend. Nu geven we een beknopte beschrijving van de algemene structuur van het fabrieksontwerppatroon.
In 5 stappen naar het openen van je eigen fabriek
Stap 1. Uw programma heeft een klasse met meerdere afstammelingen, zoals in onderstaand schema: Stap 2. U maakt eenenum
met een veld voor elke onderliggende klasse:
enum CatType {
LION,
TIGER,
FLUFFY
}
Stap 3. Bouw je fabriek. Noem het CatFactory
. Hier is de code:
class CatFactory {}
Stap 4. Creëer in je fabriek een createCat
methode die een CatType
argument nodig heeft. Hier is de code:
class CatFactory {
public Cat createCat(CatType type) {
}
}
Stap 5. Schrijf in de hoofdtekst van de methode een switch
instructie die de enum-velden opsomt en een instantie van de klasse maakt die overeenkomt met de doorgegeven enum
waarde:
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 kun je een fabriek runnen als een baas. :)
GO TO FULL VERSION