Hei venn! I dag skal vi fortsette å studere designmønstre. I denne leksjonen skal vi snakke om fabrikker. Vi skal diskutere problemet som dette mønsteret løser og se på et eksempel på hvordan en fabrikk kan hjelpe deg med å åpne en kaffebar. I tillegg vil jeg gi deg 5 enkle trinn for å lage en fabrikk. For å være sikker på at vi alle er på samme bølgelengde og at du raskt forstår dette konseptet, bør du være kjent med følgende emner:
- Arv i Java
- Innsnevring og utvidelse av referansetyper i Java
- Interaksjon mellom ulike klasser og objekter.
Hva er en fabrikk?
Fabrikkdesignmønsteret lar deg kontrollere opprettelsen av objekter. Prosessen med å lage et nytt objekt er ikke superenkelt, men det er heller ikke altfor komplisert. Vi vet alle at vi trenger operatørennew
for å lage et nytt objekt. Kanskje ser det ut til at det ikke er noe å kontrollere her, men det stemmer ikke. Anta at vår applikasjon har en viss klasse som har mange etterkommere. Det kan oppstå vanskeligheter når det er nødvendig å opprette en forekomst av en bestemt klasse avhengig av visse forhold. En fabrikk er et designmønster som hjelper til med å løse problemet med å lage ulike objekter avhengig av visse forhold. Hvordan er det for et abstrakt konsept? Dette vil bli klarere og mer spesifikt når vi ser på eksemplet nedenfor.
La oss tilberede ulike typer kaffe
Anta at vi ønsker å automatisere en kaffebar. Vi må lære programmet vårt hvordan man lager forskjellige typer kaffe. For å gjøre dette vil vi lage en kaffeklasse og noen få derivatklasser for å representere kaffetypene vi skal tilberede: Americano, cappuccino, espresso og latte. La oss starte med en generell kaffetime:
public class Coffee {
public void grindCoffee(){
// Grind the coffee
}
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
Deretter oppretter vi barneklassene:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Våre kunder kan bestille alle typer kaffe. Bestillingene deres må sendes til programmet. Dette kan gjøres på mange måter, for eksempel ved å bruke String
. Men an enum
er best for dette. Vi oppretter enum
og definerer enum-felter som tilsvarer kaffetypene som kan bestilles:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
Flott. La oss nå skrive koden for kaffebaren vår:
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 orderCoffee
kan deles inn i to deler:
- Oppretting av en spesifikk forekomst av kaffe i en
switch
uttalelse. Det er her en fabrikk gjør det den gjør - lage en bestemt type avhengig av forholdene. - Forberedelse - dette er maling, brygging og helling i en kopp.
- Trinnene som er involvert i selve tilberedningen (maling, brygging og helling i en kopp) vil forbli uendret (i det minste regner vi med dette).
- Men utvalget av kaffe kan endre seg. Kanskje vi begynner å lage mokka... Frappu... Mochacci... Uansett, en ny type kaffe.
switch
. Det er også mulig at i vår kaffebar orderCoffee
vil metoden ikke være det eneste stedet hvor vi lager forskjellige typer kaffe. Det vil derfor måtte gjøres endringer flere steder. Du forstår sikkert allerede hva jeg mener. Vi må refaktorere. Flytt blokken som er ansvarlig for å lage kaffe til en egen klasse av to grunner:
- Vi kan gjenbruke kaffekokingslogikken andre steder.
- Hvis sortimentet endres, trenger vi ikke å redigere koden overalt hvor kaffen lages. Det vil være nok å endre koden vår på bare ett sted.
Setter opp vår første fabrikk
For å gjøre dette oppretter vi en ny klasse som kun er ansvarlig for å lage de nødvendige forekomstene av 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;
}
}
Gratulerer! Vi har nettopp implementert fabrikkdesignmønsteret i sin enkleste form (nesten). Det kunne vært enda enklere om vi gjorde createCoffee
metoden statisk. Men da ville vi miste to evner:
- Evnen til å arve
SimpleCoffeeFactory
og overstyrecreateCoffee
metoden. - Muligheten til å legge til den nødvendige fabrikkimplementeringen til våre klasser.
Legger til en fabrikk til kaffebaren
La oss omskrive kaffebarklassen ved å bruke en fabrikk:
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;
}
}
Utmerket. Nå skal vi gi en kortfattet beskrivelse av den generelle strukturen til fabrikkdesignmønsteret.
5 trinn for å åpne din egen fabrikk
Trinn 1. Programmet ditt har en klasse med flere etterkommere, som i diagrammet nedenfor: Trinn 2. Du oppretter etenum
med et felt for hver barneklasse:
enum CatType {
LION,
TIGER,
FLUFFY
}
Trinn 3. Bygg fabrikken din. Kall det CatFactory
. Her er koden:
class CatFactory {}
Trinn 4. På fabrikken din, lag en createCat
metode som tar et CatType
argument. Her er koden:
class CatFactory {
public Cat createCat(CatType type) {
}
}
Trinn 5. I hoveddelen av metoden skriver du en switch
setning som teller opp enum-feltene og oppretter en forekomst av klassen som tilsvarer den beståtte enum
verdien:
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;
}
}
Nå kan du drive en fabrikk som en sjef. :)
GO TO FULL VERSION