Jakiś czas temu, podczas pogłębiania wiedzy na temat wzorców projektowych, natknąłem się na dwie zbliżone do siebie metody kreacji obiektów. Próbując zrozumieć między nimi róznicę, postanowiłem zbadać temat i popełnić na ten temat arytkuł.
Factory Method
W tym wzorcu zamiast tworzyć obiekt bezpośrednio w ciele naszych funkcji, używamy metody (fabrycznej), która jest zdefiniowana w naszej klasie bazowej. Dzięki temu podklasy decydują jaki typ zostanie stworzony.
Jak to działa?
Wyobraźmy sobie, że mamy klasę, która tworzy różne rodzaje obsługi formatów plików graficznych. Możemy mieć bazową klasę Creator, która definiuje metodę fabryczną factory_method za pomocą której będą tworzone, jakie konkretne typy instancji mają zostać utworzone.
Kod:
Na samym początku definiujemy importy:
from __future__ import annotations
from abc import ABC, abstractmethod
Następnie definiujemy klasę która będzie pełniła rolę interfejsu do procesowania obrazków:
class Image(ABC):
@abstractmethod
def open(self) -> None:
pass
@abstractmethod
def process(self) -> None:
pass
class Jpeg(Image):
def open(self) -> None:
print("Open jpg Image")
def process(self) -> None:
print("Process jpg Image")
class Png(Image):
def open(self) -> None:
print("Open png Image")
def process(self) -> None:
print("Process png Image")
class Creator(ABC):
@abstractmethod
def factory_method(self):
pass
def some_operation(self) -> str:
product = self.factory_method()
product.open()
return product
class JpegCreator(Creator):
def factory_method(self) -> Image:
return Jpeg()
class PngCreator(Creator):
def factory_method(self) -> Image:
return Png()
def use_factory(creator: Creator) -> None:
x = creator.some_operation()
x.process()
if __name__ == "__main__":
use_factory(JpegCreator())
use_factory(PngCreator())
Abstract Factory
Jak to działa?
Kod:
Jak zawsze zaczynamy od importów:
from __future__ import annotations
from abc import ABC, abstractmethod
- Image - służy do otwierania obrazków
- ImageConvertService - służy do obsługi zewnętrznego oprogramowania które zajmie się ich konwersją
class Image(ABC):
@abstractmethod
def open(self) -> None:
pass
class ImageConvertService(ABC):
@abstractmethod
def convert(self) -> None:
pass
class Jpeg(Image):
def open(self) -> None:
print("Open jpg Image")
class JpgConvertService(ImageConvertService):
def convert(self) -> None:
print("Process jpg Image")
class Png(Image):
def open(self) -> None:
print("Open png Image")
class PngConvertService(ImageConvertService):
def convert(self) -> None:
print("Process png Image")
class AbstractFactory(ABC):
@abstractmethod
def create_image_procesor(self):
pass
@abstractmethod
def create_image_convert_service(self):
pass
class JpegFactory(AbstractFactory):
def create_image_procesor(self) -> Image:
return Jpeg()
def create_image_convert_service(self):
return JpgConvertService()
class PngFactory(AbstractFactory):
def create_image_procesor(self) -> Image:
return Png()
def create_image_convert_service(self):
return PngConvertService()
def use_factory(factory: AbstractFactory) -> None:
image = factory.create_image_procesor()
image.open()
converter = factory.create_image_convert_service()
converter.convert()
if __name__ == "__main__":
use_factory(JpegFactory())
use_factory(PngFactory())
Podsumowanie
- Factory
Method: Służy do tworzenia pojedynczego obiektu i pozwala podklasom
decydować, jaki dokładnie obiekt ma być stworzony. Jest to idealne
rozwiązanie, gdy potrzebujemy elastyczności w wyborze typu obiektu.
- Abstract Factory: Służy do tworzenia rodzin powiązanych obiektów. Dzięki temu możemy tworzyć zestawy obiektów, co ułatwia zarządzanie i zapewnia spójność. Łączy zalety factory method.
Mam nadzieję, że te przykłady pomogły w zrozumieniu różnicy między tymi dwoma wzorcami.
Komentarze