Wzorzec projektowy Fabryka to Twoja przepustka do projektowania modularnego i skalowalnego kodu.
Wzorzec projektowy Fabryka jest przydatny do tworzenia obiektów. Głównym celem tego wzorca jest oddzielenie logiki tworzenia obiektów od reszty aplikacji oraz umożliwienie łatwego tworzenie różnych typów obiektów.
Do konkretnych zastosowań wzorca Fabryka należą:
- Abstrakcja tworzenia obiektów – fabryka jest odpowiedzialna za tworzenie obiektów, a nie klient, dlatego logika tworzenia obiektów jest oddzielona od reszty aplikacji.
- Tworzenie różnych typów obiektów – fabryka może tworzyć różne typy obiektów, które implementują tę samą klasę bazową lub interfejs. To pozwala na łatwe rozszerzanie aplikacji o nowe funkcjonalności.
- Tworzenie obiektów z danymi testowymi – fabryki często są używane do tworzenia obiektów z danymi testowymi, co jest przydatne przy tworzeniu testów jednostkowych.
- Elastyczność – Wzorzec fabryka umożliwia na dynamiczne tworzenie różnych implementacji tej samej klasy bazowej czy interfejsu.
Wzorzec projektowy Fabryka – przykład implementacji
Poniżej przedstawiam przykład implementacji wzorca projektowego Fabryka w PHP:
interface Vehicle {
public function getType(): string;
}
class Car implements Vehicle {
public function getType(): string {
return "Car";
}
}
class Bike implements Vehicle {
public function getType(): string {
return "Bike";
}
}
class VehicleFactory {
public static function createVehicle(string $type): Vehicle {
switch ($type) {
case "car":
return new Car();
case "bike":
return new Bike();
default:
throw new Exception("Invalid vehicle type");
}
}
}
Kod powyżej zawiera interfejs Vehicle, który zawiera metodę getType(). Klasy Car i Bike implementują ten interfejs i zwracają odpowiedni typ pojazdu. Klasa VehicleFactory jest fabryką, która posiada statyczną metodę createVehicle(), która jest odpowiedzialna za tworzenie obiektów klas Car i Bike. Metoda ta przyjmuje jako argument typ pojazdu, a następnie w zależności od tego jaki typ jest podany zwraca odpowiedni obiekt.
$car = VehicleFactory::createVehicle("car");
echo $car->getType(); // "Car"
$bike = VehicleFactory::createVehicle("bike");
echo $bike->getType(); // "Bike"
W powyższym przykładie używamy metody createVehicle z klasy VehicleFactory by utworzyć instancję klasy Car lub Bike.
Warto zauważyć, że zwiększa to abstrakcję i oddziela logikę tworzenia obiektów od reszty aplikacji. Dzięki temu w razie potrzeby, możemy łatwo zmienić sposób tworzenia obiektów bez wpływu na pozostałą część aplikacji.
Warto wspomnieć że wzorzec Fabryka jest często używany w połączeniu z innymi wzorcami projektowymi takimi jak np. Wzorzec projektowy Strategia czy też Wzorzec projektowy Builder. Dzięki temu połączeniu, tworzą one skomplikowany system, który jest bardziej elastyczny i łatwy w utrzymaniu.
Wzorzec projektowy Fabryka w Laravel
W Laravelu wzorzec fabryka jest używany w kilku miejscach, w tym:
Tworzenie obiektów modeli – Laravel używa fabryk do tworzenia obiektów modeli, które reprezentują rekordy z bazy danych. Fabryki pozwalają na łatwe utworzenie obiektów z danymi testowymi, co jest bardzo przydatne przy tworzeniu testów jednostkowych.
Tworzenie migracji – Laravel używa fabryk do generowania danych testowych do migracji, które pozwalają na przetestowanie aplikacji przed uruchomieniem jej na produkcji.
Tworzenie przykładowych danych – Laravel udostępnia także API do tworzenia przykładowych danych, które są generowane przez fabryki.
Tworzenie modeli w kontrolerach – Fabryki Laravel pozwalają także na proste tworzenie modeli bezpośrednio w kontrolerach, w związku z tym użycie konstruktora nie jest konieczne.
Widać więc, że fabryki są istotnym elementem w Laravelu, ponieważ pozwalają na generowanie danych testowych, tworzenie modeli i migracji, co wpływa na poprawienie przetestowalności aplikacji. Dzięki fabrykom kod jest bardziej czytelny, ponieważ logika tworzenia obiektów jest oddzielona od reszty aplikacji.
Wzorzec projektowy Fabryka w Symfony
W Symfony możemy również użyć fabryki do tworzenia instancji usług zależnie od określonych warunków lub konfiguracji.
Na przykład, możemy stworzyć fabrykę, która na podstawie parametru konfiguracyjnego utworzy odpowiednią instancję usługi do obsługi operacji na plikach.
class FileServiceFactory {
public static function create(string $storageType): FileServiceInterface {
switch ($storageType) {
case 'local':
return new LocalFileService();
case 'cloud':
return new CloudFileService();
default:
throw new \InvalidArgumentException('Invalid storage type');
}
}
}
// Użycie fabryki
$fileService = FileServiceFactory::create('cloud');
$fileService->uploadFile($file);