Паттерн Абстрактная фабрика, реализация на python

Абстрактная фабрика (англ.Abstract factory) — порождающий шаблон проектирования, предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов. Шаблон реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы (например, для оконного интерфейса он может создавать окна и кнопки). Затем пишутся классы, реализующие этот интерфейс.

Реализация паттерна абстрактная фабрика с примером на python. Начнем сразу с примера

Допустим у нас есть 2 операционные системы Mac Os и Linux, нам необходимо реализовать произвольное окно с кнопкой или кнопками в каждой из этих операционных систем. Естественно окна и кнопки в MacOs и linux выглядят по разному, так сказать имеют разные стили оформления.

Наша задача состоит в том, что бы создать универсальный интерфейс который будет создавать окно с кнопкой в не зависимости от того на какой операционной системе запущенна программа.

Т.е. функции которая будет конструировать окно с кнопкой, будет работать вне зависимости от того какое окно мы захотим создать

Для начала опишем класс абстрактной фабрики

class WindowFactory:
    @classmethod
    def create_window(cls, name):
    """Метод создания окна, возврашает класс окно"""
        return cls.Window(name)
    @classmethod
    def create_button(cls, name):
    """Метод создания кнопки, возврашает класс кнопки"""
        return cls.Button(name)

Абстрактная фабрика готова, обратите внимание на строки return cls.Window(name) и return cls.Button(name), как видите в обоих случаях мы возвращаем некий класс(cls) у которого есть подкласс Window\Button, но в настоящий момент мы не описали ни класс  Window, ни класс Button, давайте это сделаем.

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

class MacOsFactory(WindowFactory):
    class Window:
        def __init__(self, name):
            self.name = name
            self.button = []
            self.style = 'Mac Os window style'
        def add_button(self, btn):
            self.button.append(btn.name)
        def show(self):
            print( '{} - {} and {}'.format(self.name, self.style, self.button))
    class Button:
        def __init__(self, name):
            self.name = name
            self.style = 'Mac Os button style'

И тоже самое для Linux

class LinuxFactory(WindowFactory):
    class Window:
        def __init__(self, name):
            self.name = name
            self.button = []
            self.style = 'Ubuntu window style'
        def add_button(self, btn):
            self.button.append(btn.name)
        def show(self):
            print( '{} - {} and {}'.format(self.name, self.style, self.button))
    class Button:
        def __init__(self, name):
            self.name = name
            self.style = 'Ubuntu button style'

Как не сложно заметить название методов у обоих классов полностью совпадает.

Далее осталось реализовать функцию которая будет создавать окна при помощи абстрактной фабрики:

def create_dialog(factory):
    wind = factory.create_window('Form1')
    button = factory.create_button('Button1')
    wind.add_button(button)
    return wind

Данная функция принимает на вход 1-ин параметр — класс конкретной фабрики, в нашем случае это может быть класс MacOsFactory или класс LinuxFactory. Это очень важный для понимания момент поэтому, разберем по порядку, что делает функция.

Итак, допустим мы выполнили её с параметром MacOsFactory т.е.:

  1. create_dialog(MacOsFactory)
  2. В теле функции выполнится следующий код: wind = MacOsFactory.create_window(‘Form1’) , где create_window — класс метод абстрактной фабрики
  3. В свою очередь класс-метод create_window вернет в нашем случае =>  MacOsFactory.Window(‘Form1’)
  4. Экземпляр которого мы записываем в переменную wind.

Дальнейшие действия в функции аналогичны и я думаю не нуждаются в детальных пояснениях.

Теперь когда наша программа запуститься, она каким то образом определит на какой операционной системы произошел запуск, и передаст в функцию нужный параметр, для Linux => LinuxFactory для macOs => MacOsFactory.

# Допустим мы запустились на Linux
w = create_window(LinuxFactory)
w.show()
>>> Form1 - Ubuntu window style and ['Button1']

python_job_interview –  здесь собраны все возможные вопросы и ответы с реальных Python собеседований.

golang_interview – канал поможет пройти Golang собеседование.

machinelearning_interview – канал подготовит к собеседованию по машинному обучению и алгоритмам .

data_analysis_ml – самая востребованная Python профессия.

источник

Ответить