Что такое паттерн ‘Абстрактная фабрика’ и какую проблему он решает?

Ответ

Абстрактная фабрика — это порождающий паттерн проектирования, который предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов.

Ключевая идея: Паттерн инкапсулирует логику выбора конкретной реализации и позволяет клиенту работать с абстрактными типами, не зная, какая именно фабрика и какие продукты были созданы.

Когда использовать:

  • Когда система должна быть независима от процесса создания, композиции и представления своих продуктов.
  • Когда нужно работать с одним из нескольких семейств продуктов (например, GUI для разных ОС: Windows, macOS).
  • Когда вы хотите предоставить библиотеку классов, раскрывая только их интерфейсы, но не реализацию.

Пример на Python: Создадим фабрики для производства мебели в разных стилях (модерн и викторианский). Каждая фабрика производит полный набор: стул и стол.

from abc import ABC, abstractmethod

# --- Абстрактные продукты ---
class AbstractChair(ABC):
    @abstractmethod
    def sit_on(self) -> str:
        pass

class AbstractTable(ABC):
    @abstractmethod
    def put_on(self) -> str:
        pass

# --- Конкретные продукты (стиль Модерн) ---
class ModernChair(AbstractChair):
    def sit_on(self) -> str:
        return "Сидим на современном стуле."

class ModernTable(AbstractTable):
    def put_on(self) -> str:
        return "Ставим на современный стол."

# --- Абстрактная фабрика ---
class AbstractFurnitureFactory(ABC):
    @abstractmethod
    def create_chair(self) -> AbstractChair:
        pass

    @abstractmethod
    def create_table(self) -> AbstractTable:
        pass

# --- Конкретная фабрика (Модерн) ---
class ModernFurnitureFactory(AbstractFurnitureFactory):
    def create_chair(self) -> AbstractChair:
        return ModernChair()

    def create_table(self) -> AbstractTable:
        return ModernTable()

# --- Клиентский код ---
def client_code(factory: AbstractFurnitureFactory):
    chair = factory.create_chair()
    table = factory.create_table()
    print(chair.sit_on())
    print(table.put_on())

# Используем фабрику для создания мебели в стиле Модерн
print("Клиент: Заказываю мебель в стиле Модерн.")
client_code(ModernFurnitureFactory())

Клиентский код зависит только от абстрактных классов AbstractFurnitureFactory, AbstractChair, AbstractTable, что позволяет легко подменить фабрику (например, на VictorianFurnitureFactory) без изменения самого клиента.