Получи случайную криптовалюту за регистрацию!

#паттерны Введение Сегодня мы рассмотрим паттерн проектирова | Holy Python

#паттерны

Введение

Сегодня мы рассмотрим паттерн проектирования "Абстрактная фабрика".

Классификация

Тип: Порождающий

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

Грубо говоря, абстрактная фабрика - это "фабрика фабрик", данный паттерн позволяет решить проблему создания целых семейств связанных объектов, без указания конкретных классов продуктов.
С помощью абстрактной фабрики вы можете предоставить библиотеку объектов не расскрывая их реализацию.

Из чего состоит и как работает данный паттерн

1. Абстрактного класса/Интерфейса абстрактной фабрики. Содержит абстрактные методы которые возвращают абстрактные продукты, связанные одной конпцецией.

class AbstractFactory(ABC):
@abstractmethod
def create_product_a(self):
...

@abstractmethod
def create_product_b(self):
...

2. Конретные фабрики. Конкретные фабрики реализут операции которые создают конкретные продукты.

class ConcreteFactory1(AbstractFactory):
def create_product_a(self):
return ConcreteProductA1()

def create_product_b(self):
return ConcreteProductB1()

class ConcreteFactory2(AbstractFactory):
def create_product_a(self):
return ConcreteProductA2()

def create_product_b(self):
return ConcreteProductB2()

3. Абстрактные классы продуктов. Реализуют интерфейс для всех конретных продуктов своего семейства.

class AbstractProductA(ABC):
@abstractmethod
def very_important_super_function_a(self) -> str:
...

class AbstractProductB(ABC):
@abstractmethod
def very_important_super_function_b(self) -> str:
...

4. Конкретные продукты. Реализуют абстрактные продукты. Продукты одного семейства не могут взаимодействовать, с продуктами другого семейства.

class ConcreteProductA1(AbstractProductA):
def very_important_super_function_a(self) -> str:
return "Product A1"


class ConcreteProductA2(AbstractProductA):
def very_important_super_function_a(self) -> str:
return "Product A2"

class ConcreteProductB1(AbstractProductB):
def very_important_super_function_b(self) -> str:
return "Product B1"


class ConcreteProductB2(AbstractProductB):
def very_important_super_function_b(self) -> str:
return "Product B2"

5. Клиент. Клиентский код работает исключительно с абстрактной фабрикой и абстрактными продуктами.

def client(factory: AbstractFactory) -> str:
return factory.create_product_a().very_important_super_function_a()

for factory in (ConcreteFactory1, ConcreteFactory2, ...):
client(factory)

Плюсы данного паттерна

1. Реализует принцип открытости/закрытости.

2. Упращает поддержку кода.

3. Выделяет код производства продуктов в одно место, упрощая поддержку кода.

Минусы данного паттерна

1. Снижает читаемость программы из-за введения множества дополнительных классов.

Пример и задача

Дед Мороз и Пасхальный кролик не успевают сделать игрушки к празднику, которые они будут дарить детям.
Все существует 3 вида игрушек:

1. Лошадка
2. Зайчик
3. Шарик

Всё было бы просто однако Деду Морозу нужны игрушки в новогоднем стиле, а пасхальному кролику в пасхальном.
Создайте абстрактную фабрику игрушек и спасите эти праздники!

Пример из реального кода

Пример из реального кода предоставил @Tishka17. Он разработал замечательный фреймворк aiogram_dialog для разработки интерактивных диалогов и меню в телеграмм ботах, как обычное приложение с графическим интерфейсом.

Вот здесь он использует данный паттерн: https://github.com/Tishka17/aiogram_dialog/blob/develop/aiogram_dialog/manager/manager_middleware.py#L23

Вот его объяснение, какую задачу он решает в данном случае: