Ответ
Фабрика (Factory) — это порождающий паттерн проектирования, который предоставляет интерфейс для создания объектов, но позволяет подклассам изменять тип создаваемых объектов. Он инкапсулирует логику инстанцирования, делая код более гибким и расширяемым.
В Python существует несколько вариаций этого паттерна.
1. Простая Фабрика (Simple Factory)
Это не канонический паттерн из банды четырех (GoF), а скорее популярная идиома. Один класс или функция решает, какой объект создать, на основе переданного параметра.
Применение: Когда логика создания объектов несложная и не требует расширения через наследование.
class Dog:
def speak(self): return "Woof!"
class Cat:
def speak(self): return "Meow!"
# Простая фабрика в виде функции
def get_pet(pet_type: str):
"""Создает объект животного по его типу."""
if pet_type == "dog":
return Dog()
elif pet_type == "cat":
return Cat()
raise ValueError("Unknown pet type")
# Использование
my_dog = get_pet("dog")
print(my_dog.speak()) # -> Woof!
2. Фабричный метод (Factory Method)
Это канонический паттерн. Он определяет абстрактный метод для создания объекта (factory_method), а конкретные реализации этого метода находятся в подклассах. Таким образом, создание объекта делегируется дочерним классам.
Применение: Когда класс не может заранее знать, объекты каких подклассов ему нужно создавать, или когда вы хотите дать пользователям возможность расширять вашу библиотеку.
from abc import ABC, abstractmethod
# Абстрактный продукт
class Animal(ABC):
@abstractmethod
def speak(self): pass
# Конкретные продукты
class Dog(Animal):
def speak(self): return "Woof!"
class Cat(Animal):
def speak(self): return "Meow!"
# Абстрактный создатель (фабрика)
class AnimalFactory(ABC):
@abstractmethod
def create_animal(self) -> Animal:
pass
# Конкретные создатели
class DogFactory(AnimalFactory):
def create_animal(self) -> Animal:
return Dog()
class CatFactory(AnimalFactory):
def create_animal(self) -> Animal:
return Cat()
# Использование
def get_animal_from_factory(factory: AnimalFactory):
animal = factory.create_animal()
print(f"Created animal says: {animal.speak()}")
get_animal_from_factory(DogFactory()) # -> Created animal says: Woof!
get_animal_from_factory(CatFactory()) # -> Created animal says: Meow!
3. Абстрактная фабрика (Abstract Factory)
Этот паттерн позволяет создавать семейства взаимосвязанных объектов, не привязываясь к их конкретным классам. Он предоставляет интерфейс для создания целого набора продуктов.
Применение: Когда система должна быть независимой от того, как создаются, компонуются и представляются ее продукты.
# Пример: Фабрика для создания GUI элементов под разные ОС
# Абстрактные продукты
class Button(ABC):
@abstractmethod
def render(self): pass
class Checkbox(ABC):
@abstractmethod
def render(self): pass
# Абстрактная фабрика
class GUIFactory(ABC):
@abstractmethod
def create_button(self) -> Button: pass
@abstractmethod
def create_checkbox(self) -> Checkbox: pass
# Конкретная фабрика для Windows
class WinFactory(GUIFactory):
def create_button(self) -> Button: return WinButton()
def create_checkbox(self) -> Checkbox: return WinCheckbox()
# Конкретная фабрика для MacOS
class MacFactory(GUIFactory):
def create_button(self) -> Button: return MacButton()
def create_checkbox(self) -> Checkbox: return MacCheckbox()
# ... реализации конкретных продуктов WinButton, MacButton и т.д. ...
Основные преимущества паттерна:
- Инкапсуляция: Скрывает логику создания объектов от клиентского кода.
- Гибкость: Упрощает добавление новых типов продуктов, не изменяя существующий клиентский код.
- Соблюдение принципов SOLID: Соответствует принципу открытости/закрытости (Open/Closed Principle) и принципу единственной ответственности (Single Responsibility Principle).