Во время разработки часто нужно создать объекты, которые могут иметь сложную логику инициализации. Или мы хотим скрыть подробности создания объекта от пользователя.
Для решения этой задачи был разработан паттерн проектирования «Фабрика». В этом уроке мы рассмотрим, как он работает.
Как работает паттерн «Фабрика»
В Python мы можем создать «фабрику» — функцию или метод, который выбирает нужный класс, создает объект и возвращает его. Вместо использования нескольких условных конструкций мы можем использовать диспетчеризацию по словарю. Это сделает нашу фабрику более элегантной и легко расширяемой.
Допустим, у нас есть класс для зоопарка и различные типы животных: Lion
, Tiger
и Bear
. Эти животные могут издавать звуки, поэтому у них будет общий метод make_sound
:
class Animal:
def make_sound(self):
pass
class Lion(Animal):
def make_sound(self):
return "Roar"
class Tiger(Animal):
def make_sound(self):
return "Growl"
class Bear(Animal):
def make_sound(self):
return "Grr"
Здесь мы создали родительский класс Animal
с методом make_sound
, а затем три класса Lion
, Tiger
и Bear
, каждый из которых реализует этот метод по-своему. Такой подход позволяет создавать объекты, которые, несмотря на различия в деталях реализации, обладают общими элементами и могут быть использованы в коде взаимозаменяемо.
Теперь представим, что нам нужно создать фабрику, которая будет создавать животных для нашего зоопарка. Вместо вызова конструктора каждого класса животного напрямую мы можем создать фабрику, которая будет делать это за нас:
class AnimalFactory:
animal_classes = {"Lion": Lion, "Tiger": Tiger, "Bear": Bear}
def create_animal(animal_type):
if animal_type in AnimalFactory.animal_classes:
return AnimalFactory.animal_classes[animal_type]()
else:
raise ValueError("Invalid animal type")
В этом коде класс AnimalFactory
содержит словарь animal_classes
, который используется для диспетчеризации. Это позволяет избежать использования elif
и создать более гибкую систему, которую можно легко расширить, добавив новые типы животных в словарь.
Заметьте, как логика создания объектов животных инкапсулирована внутри фабрики. Это позволяет создавать новых животных без необходимости знать детали реализации каждого класса.
Теперь мы можем использовать нашу фабрику для создания животных:
lion = AnimalFactory.create_animal("Lion")
print(lion.make_sound()) # Roar
tiger = AnimalFactory.create_animal("Tiger")
print(tiger.make_sound()) # Growl
bear = AnimalFactory.create_animal("Bear")
print(bear.make_sound()) # Grr
Здесь мы используем фабрику для создания объектов различных типов. Каждое созданное животное имеет метод make_sound
. Мы вызываем его, чтобы показать, что объекты действительно были созданы.
Этот пример показывает основной принцип работы паттерна «Фабрика». Он изолирует код от деталей создания объектов, что позволяет легко добавлять новые типы объектов и делает код более гибким и легко поддерживаемым.
Выводы
Паттерн «Фабрика» является мощным инструментом для создания объектов, особенно, когда эти объекты имеют сложную логику создания или когда нужно создавать разные типы объектов.
При этом нужно понимать, если у вас есть только один тип объекта, который вам нужно создавать, или если логика создания объекта проста и не изменяется, то использование фабрики может быть избыточным и усложнить код.
В случае, когда нужно создавать разные типы объектов или когда процесс создания объекта включает в себя сложную логику или множество шагов, «Фабрика» может сделать код более структурированным и понятным.
Дополнительные материалы
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.