Ответ
Абстрактная фабрика — это порождающий паттерн проектирования, который предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретные классы.
Проблема
Представьте, что вы создаете UI-кит, который должен поддерживать несколько операционных систем (Windows, macOS). Вам нужны кнопки, чекбоксы и другие элементы, которые выглядят и ведут себя по-разному в каждой ОС. Если создавать объекты напрямую (button = WinButton()), ваш код будет жестко связан с конкретными классами, и добавление новой ОС потребует изменения всего клиентского кода.
Решение
Абстрактная фабрика предлагает создать общий интерфейс (GUIFactory) с методами для создания каждого продукта в семействе (create_button, create_checkbox). Затем для каждой ОС создается своя конкретная фабрика (WinFactory, MacFactory), которая реализует этот интерфейс и возвращает объекты, соответствующие данной ОС.
Клиентский код работает только с интерфейсом фабрики, не зная, какая конкретная фабрика ему передана.
Пример на Python
from abc import ABC, abstractmethod
# --- Абстрактные продукты ---
class Button(ABC):
@abstractmethod
def render(self) -> str:
pass
class Checkbox(ABC):
@abstractmethod
def render(self) -> str:
pass
# --- Абстрактная фабрика ---
class GUIFactory(ABC):
@abstractmethod
def create_button(self) -> Button:
pass
@abstractmethod
def create_checkbox(self) -> Checkbox:
pass
# --- Конкретные фабрики и продукты для Windows ---
class WinButton(Button):
def render(self) -> str:
return "Отрисовка кнопки в стиле Windows"
class WinCheckbox(Checkbox):
def render(self) -> str:
return "Отрисовка чекбокса в стиле Windows"
class WinFactory(GUIFactory):
def create_button(self) -> Button:
return WinButton()
def create_checkbox(self) -> Checkbox:
return WinCheckbox()
# --- Конкретные фабрики и продукты для macOS ---
class MacButton(Button):
def render(self) -> str:
return "Отрисовка кнопки в стиле macOS"
class MacCheckbox(Checkbox):
def render(self) -> str:
return "Отрисовка чекбокса в стиле macOS"
class MacFactory(GUIFactory):
def create_button(self) -> Button:
return MacButton()
def create_checkbox(self) -> Checkbox:
return MacCheckbox()
# --- Клиентский код ---
def client_code(factory: GUIFactory):
button = factory.create_button()
checkbox = factory.create_checkbox()
print(button.render())
print(checkbox.render())
# Используем фабрику для Windows
print("Клиент: работаю с Windows UI")
client_code(WinFactory())
# Используем фабрику для macOS
print("nКлиент: работаю с macOS UI")
client_code(MacFactory())
Когда использовать
- Когда система не должна зависеть от того, как создаются, компонуются и представляются входящие в нее объекты.
- Когда нужно работать с одним из нескольких семейств объектов, и эти семейства спроектированы для совместного использования.
- Когда вы хотите предоставить библиотеку классов, раскрывая только их интерфейсы, но не реализацию.