Created
May 28, 2019 17:49
-
-
Save moonzlo/d3869bc361696e4e5f727393f394fd7f to your computer and use it in GitHub Desktop.
Паттерн Абстрактная фабрика
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from __future__ import annotations | |
| from abc import ABC, abstractmethod | |
| class AbstractFactory(ABC): | |
| """ | |
| Интерфейс Абстрактной Фабрики объявляет набор методов, которые возвращают | |
| различные абстрактные продукты. Эти продукты называются семейством и связаны | |
| темой или концепцией высокого уровня. Продукты одного семейства обычно могут | |
| взаимодействовать между собой. Семейство продуктов может иметь несколько | |
| вариаций, но продукты одной вариации несовместимы с продуктами другой. | |
| """ | |
| @abstractmethod | |
| def create_product_a(self) -> AbstractProductA: | |
| pass | |
| @abstractmethod | |
| def create_product_b(self) -> AbstractProductB: | |
| pass | |
| class ConcreteFactory1(AbstractFactory): | |
| """ | |
| Конкретная Фабрика производит семейство продуктов одной вариации. Фабрика | |
| гарантирует совместимость полученных продуктов. Обратите внимание, что | |
| сигнатуры методов Конкретной Фабрики возвращают абстрактный продукт, в то | |
| время как внутри метода создается экземпляр конкретного продукта. | |
| """ | |
| def create_product_a(self) -> ConcreteProductA1: | |
| return ConcreteProductA1() | |
| def create_product_b(self) -> ConcreteProductB1: | |
| return ConcreteProductB1() | |
| class ConcreteFactory2(AbstractFactory): | |
| """ | |
| Каждая Конкретная Фабрика имеет соответствующую вариацию продукта. | |
| """ | |
| def create_product_a(self) -> ConcreteProductA2: | |
| return ConcreteProductA2() | |
| def create_product_b(self) -> ConcreteProductB2: | |
| return ConcreteProductB2() | |
| class AbstractProductA(ABC): | |
| """ | |
| Каждый отдельный продукт семейства продуктов должен иметь базовый интерфейс. | |
| Все вариации продукта должны реализовывать этот интерфейс. | |
| """ | |
| @abstractmethod | |
| def useful_function_a(self) -> str: | |
| pass | |
| """ | |
| Конкретные продукты создаются соответствующими Конкретными Фабриками. | |
| """ | |
| class ConcreteProductA1(AbstractProductA): | |
| def useful_function_a(self) -> str: | |
| return "The result of the product A1." | |
| class ConcreteProductA2(AbstractProductA): | |
| def useful_function_a(self) -> str: | |
| return "The result of the product A2." | |
| class AbstractProductB(ABC): | |
| """ | |
| Базовый интерфейс другого продукта. Все продукты могут взаимодействовать | |
| друг с другом, но правильное взаимодействие возможно только между продуктами | |
| одной и той же конкретной вариации. | |
| """ | |
| @abstractmethod | |
| def useful_function_b(self) -> None: | |
| """ | |
| Продукт B способен работать самостоятельно... | |
| """ | |
| pass | |
| @abstractmethod | |
| def another_useful_function_b(self, collaborator: AbstractProductA) -> None: | |
| """ | |
| ...а также взаимодействовать с Продуктами Б той же вариации. | |
| Абстрактная Фабрика гарантирует, что все продукты, которые она создает, | |
| имеют одинаковую вариацию и, следовательно, совместимы. | |
| """ | |
| pass | |
| """ | |
| Конкретные Продукты создаются соответствующими Конкретными Фабриками. | |
| """ | |
| class ConcreteProductB1(AbstractProductB): | |
| def useful_function_b(self) -> str: | |
| return "The result of the product B1." | |
| """ | |
| Продукт B1 может корректно работать только с Продуктом A1. Тем не менее, он | |
| принимает любой экземпляр Абстрактного Продукта А в качестве аргумента. | |
| """ | |
| def another_useful_function_b(self, collaborator: AbstractProductA) -> str: | |
| result = collaborator.useful_function_a() | |
| return f"The result of the B1 collaborating with the ({result})" | |
| class ConcreteProductB2(AbstractProductB): | |
| def useful_function_b(self) -> str: | |
| return "The result of the product B2." | |
| def another_useful_function_b(self, collaborator: AbstractProductA): | |
| """ | |
| Продукт B2 может корректно работать только с Продуктом A2. Тем не менее, | |
| он принимает любой экземпляр Абстрактного Продукта А в качестве | |
| аргумента. | |
| """ | |
| result = collaborator.useful_function_a() | |
| return f"The result of the B2 collaborating with the ({result})" | |
| def client_code(factory: AbstractFactory) -> None: | |
| """ | |
| Клиентский код работает с фабриками и продуктами только через абстрактные | |
| типы: Абстрактная Фабрика и Абстрактный Продукт. Это позволяет передавать | |
| любой подкласс фабрики или продукта клиентскому коду, не нарушая его. | |
| """ | |
| product_a = factory.create_product_a() | |
| product_b = factory.create_product_b() | |
| print(f"{product_b.useful_function_b()}") | |
| print(f"{product_b.another_useful_function_b(product_a)}", end="") | |
| if __name__ == "__main__": | |
| """ | |
| Клиентский код может работать с любым конкретным классом фабрики. | |
| """ | |
| print("Client: Testing client code with the first factory type:") | |
| client_code(ConcreteFactory1()) | |
| print("\n") | |
| print("Client: Testing the same client code with the second factory type:") | |
| client_code(ConcreteFactory2()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment