Реализация паттерна абстрактная фабрика с примером на 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 т.е.:
- create_dialog(MacOsFactory)
- В теле функции выполнится следующий код: wind = MacOsFactory.create_window(‘Form1’) , где create_window — класс метод абстрактной фабрики
- В свою очередь класс-метод create_window вернет в нашем случае => MacOsFactory.Window(‘Form1’)
- Экземпляр которого мы записываем в переменную wind.
Дальнейшие действия в функции аналогичны и я думаю не нуждаются в детальных пояснениях.
Теперь когда наша программа запуститься, она каким то образом определит на какой операционной системы произошел запуск, и передаст в функцию нужный параметр, для Linux => LinuxFactory для macOs => MacOsFactory.
# Допустим мы запустились на Linux w = create_window(LinuxFactory) w.show() >>> Form1 - Ubuntu window style and ['Button1']