Cześć przyjacielu! Dzisiaj będziemy kontynuować badanie wzorców projektowych. W tej lekcji porozmawiamy o fabrykach. Omówimy problem, który rozwiązuje ten wzorzec i przyjrzymy się przykładowi, jak fabryka może pomóc w otwarciu kawiarni. Dodatkowo podam 5 prostych kroków do stworzenia fabryki.
Aby upewnić się, że wszyscy nadajemy na tych samych falach i że szybko zrozumiesz tę koncepcję, powinieneś zapoznać się z następującymi tematami:
Krok 2. Tworzysz pole

- Dziedziczenie w Javie
- Zawężanie i rozszerzanie typów referencyjnych w Javie
- Interakcja między różnymi klasami i obiektami.
Co to jest fabryka?
Wzorzec projektowania fabryki pozwala kontrolować tworzenie obiektów. Proces tworzenia nowego obiektu nie jest super prosty, ale nie jest też przesadnie skomplikowany. Wszyscy wiemy, że potrzebujemynew
operatora do stworzenia nowego obiektu. Być może wydaje się, że nie ma tu nic do kontrolowania, ale to nieprawda. Załóżmy, że nasza aplikacja ma pewną klasę, która ma wielu potomków. Trudności mogą pojawić się, gdy konieczne jest utworzenie instancji określonej klasy w zależności od określonych warunków. Fabryka to wzorzec projektowy, który pomaga rozwiązać problem tworzenia różnych obiektów w zależności od określonych warunków . Jak to się ma do abstrakcyjnego pojęcia? Stanie się to jaśniejsze i bardziej szczegółowe, gdy spojrzymy na poniższy przykład.
Przygotujmy różne rodzaje kawy
Załóżmy, że chcemy zautomatyzować kawiarnię. Musimy nauczyć nasz program, jak robić różne rodzaje kawy. W tym celu utworzymy klasę kawy i kilka klas pochodnych reprezentujących rodzaje kawy, które będziemy przygotowywać: Americano, cappuccino, espresso i latte. Zacznijmy od ogólnej klasy kawy:
public class Coffee {
public void grindCoffee(){
// Grind the coffee
}
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
Następnie utworzymy jego klasy potomne:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Nasi klienci mogą zamówić każdy rodzaj kawy. Ich rozkazy muszą zostać przekazane do programu. Można to zrobić na wiele sposobów, na przykład za pomocą String
. Ale enum
najlepszy jest do tego. Stworzymy enum
i zdefiniujemy pola wyliczeniowe odpowiadające rodzajom kawy, które można zamówić:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
Świetnie. Teraz napiszmy kod dla naszej kawiarni:
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;
}
}
Metodę orderCoffee
można podzielić na dwie części:
- Stworzenie konkretnego egzemplarza kawy w
switch
zestawieniu. W tym miejscu fabryka robi to, co robi — tworzy określony typ w zależności od warunków. - Przygotowanie — to mielenie, zaparzanie i nalewanie do filiżanki.
- Czynności związane z samym przygotowaniem (mielenie, zaparzanie i nalewanie do filiżanki) pozostaną niezmienione (przynajmniej na to liczymy).
- Ale asortyment kaw może ulec zmianie. Może zaczniemy robić mokkę... Frappu... Mochacci... Nieważne, nowy rodzaj kawy.
switch
instrukcji metody. Niewykluczone również, że w naszej kawiarni orderCoffee
metoda nie będzie jedynym miejscem, w którym będziemy tworzyć różne rodzaje kaw. W rezultacie zmiany będą musiały zostać wprowadzone w kilku miejscach. Pewnie już rozumiesz, o co mi chodzi. Musimy dokonać refaktoryzacji. Przenieś blok odpowiedzialny za tworzenie kawy do osobnej klasy z dwóch powodów:
- Możemy ponownie wykorzystać logikę parzenia kawy w innych miejscach.
- Jeśli zmieni się asortyment, nie będziemy musieli edytować kodu wszędzie tam, gdzie powstaje kawa. Wystarczy zmienić nasz kod w jednym miejscu.
Założenie naszej pierwszej fabryki
W tym celu utworzymy nową klasę, która będzie odpowiedzialna tylko za tworzenie niezbędnych wystąpień klas kawy:
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;
}
}
Gratulacje! Właśnie zaimplementowaliśmy wzorzec projektowania fabryki w jego najprostszej (prawie) formie. Mogłoby być jeszcze prościej, gdybyśmy uczynili createCoffee
metodę statyczną. Ale wtedy stracilibyśmy dwie możliwości:
- Możliwość dziedziczenia
SimpleCoffeeFactory
i zastępowaniacreateCoffee
metody. - Możliwość dodania wymaganej implementacji fabrycznej do naszych klas.
Dodanie fabryki do kawiarni
Przepiszmy klasę kawiarni, używając fabryki:
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;
}
}
Doskonały. Teraz przedstawimy zwięzły opis ogólnej struktury wzorca projektowego fabryki.
5 kroków do otwarcia własnej fabryki
Krok 1. Twój program ma klasę z kilkoma potomkami, jak na poniższym diagramie:
enum
z polem dla każdej klasy potomnej:
enum CatType {
LION,
TIGER,
FLUFFY
}
Krok 3. Zbuduj swoją fabrykę. Nazwij to CatFactory
. Oto kod:
class CatFactory {}
Krok 4. Utwórz w swojej fabryce createCat
metodę, która pobiera CatType
argument. Oto kod:
class CatFactory {
public Cat createCat(CatType type) {
}
}
Krok 5. W ciele metody napisz switch
instrukcję, która wylicza pola enum i tworzy instancję klasy odpowiadającą przekazanej enum
wartości:
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;
}
}
Teraz możesz prowadzić fabrykę jak szef. :)
GO TO FULL VERSION