Ответ
Паттерн Абстрактная Фабрика не "понимает" сам, какую реализацию выбрать. Он делегирует эту ответственность конкретной реализации фабрики, которую выбирает клиентский код на этапе инициализации приложения.
Основная идея — изолировать клиентский код от конкретных классов создаваемых продуктов. Клиент работает только с абстрактными интерфейсами как фабрики, так и продуктов.
Выбор конкретной фабрики происходит один раз, обычно на основе:
- Конфигурации: Параметр в конфигурационном файле (например,
theme = "dark"). - Окружения: Определение операционной системы или других переменных окружения.
- Пользовательского ввода: Явный выбор пользователя в настройках.
Пример на Python:
from abc import ABC, abstractmethod
# 1. Абстрактные продукты
class Button(ABC):
@abstractmethod
def paint(self): pass
class Checkbox(ABC):
@abstractmethod
def paint(self): pass
# 2. Абстрактная фабрика
class GUIFactory(ABC):
@abstractmethod
def create_button(self) -> Button: pass
@abstractmethod
def create_checkbox(self) -> Checkbox: pass
# 3. Конкретные реализации фабрик и продуктов для Windows
class WinButton(Button):
def paint(self): return "Render a button in Windows style"
class WinCheckbox(Checkbox):
def paint(self): return "Render a checkbox in Windows style"
class WinFactory(GUIFactory):
def create_button(self) -> Button: return WinButton()
def create_checkbox(self) -> Checkbox: return WinCheckbox()
# 4. Конкретные реализации для MacOS
class MacButton(Button):
def paint(self): return "Render a button in macOS style"
class MacCheckbox(Checkbox):
def paint(self): return "Render a checkbox in macOS style"
class MacFactory(GUIFactory):
def create_button(self) -> Button: return MacButton()
def create_checkbox(self) -> Checkbox: return MacCheckbox()
# 5. Клиентский код выбирает фабрику в зависимости от конфигурации
def get_application(os_type: str):
if os_type == "windows":
factory = WinFactory()
elif os_type == "mac":
factory = MacFactory()
else:
raise ValueError("Unknown OS type")
# Клиент работает только с абстракциями
button = factory.create_button()
print(button.paint())
# Инициализация приложения
CURRENT_OS = "mac"
get_application(CURRENT_OS)
# Вывод: Render a button in macOS style
Таким образом, система остается независимой от того, как именно создаются и компонуются ее объекты. Замена семейства продуктов сводится к замене одной конкретной фабрики.
Ответ 18+ 🔞
Да ты посмотри, какой народ безмозглый, блядь! Сидят, думают, что паттерн Абстрактная Фабрика сам, как хитрая жопа, решает, что ему создавать. Да ни хуя подобного, ёпта!
Он эту ответственность, как манда с ушами, на откуп конкретной фабрике отдаёт! А кто эту фабрику выбирает? Да клиентский код, сука, на старте приложения! Всё просто, как хуй с горы.
Смысл-то в чём? Изолировать клиента от этих ваших конкретных классов продуктов, чтобы он с одними только интерфейсами работал. А выбор фабрики — это разовое дело, обычно на основе:
- Конфига: Типа прописали в файлике
theme = "dark". - Окружения: Определили, виндовс ты или мак.
- Пользователя: Он сам в настройках тыкнул.
Смотри, как на Python:
from abc import ABC, abstractmethod
# 1. Абстрактные продукты (ни о чём не говорят, просто договорённость)
class Button(ABC):
@abstractmethod
def paint(self): pass
class Checkbox(ABC):
@abstractmethod
def paint(self): pass
# 2. Абстрактная фабрика (тоже пустозвон, но важный)
class GUIFactory(ABC):
@abstractmethod
def create_button(self) -> Button: pass
@abstractmethod
def create_checkbox(self) -> Checkbox: pass
# 3. Конкретная реализация для Windows (вот где мясо, блядь)
class WinButton(Button):
def paint(self): return "Нарисовать кнопку в стиле Windows"
class WinCheckbox(Checkbox):
def paint(self): return "Нарисовать галочку в стиле Windows"
class WinFactory(GUIFactory):
def create_button(self) -> Button: return WinButton()
def create_checkbox(self) -> Checkbox: return WinCheckbox()
# 4. Конкретная реализация для MacOS (другое мясо, но тоже мясо)
class MacButton(Button):
def paint(self): return "Нарисовать кнопку в стиле macOS"
class MacCheckbox(Checkbox):
def paint(self): return "Нарисовать галочку в стиле macOS"
class MacFactory(GUIFactory):
def create_button(self) -> Button: return MacButton()
def create_checkbox(self) -> Checkbox: return MacCheckbox()
# 5. Клиентский код. Вот он, сука, решает, какую фабрику взять!
def запустить_приложение(тип_оси: str):
if тип_оси == "windows":
фабрика = WinFactory()
elif тип_оси == "mac":
фабрика = MacFactory()
else:
raise ValueError("Неизвестная ось, иди нахуй")
# А дальше клиент тупо юзает абстракции, ему похуй
кнопка = фабрика.create_button()
print(кнопка.paint())
# И вот инициализация, момент выбора!
ТЕКУЩАЯ_ОС = "mac"
запустить_приложение(ТЕКУЩАЯ_ОС)
# Выведет: Нарисовать кнопку в стиле macOS
Вот и вся магия, ебать мои старые костыли! Системе похуй, как там объекты создаются и компонуются. Захотел сменить всё семейство продуктов — просто подмени одну фабрику, и в рот меня чих-пых, готово!