Шаг 87.
Python: тонкости программирования. Классы и ООП. Методы экземпляра, класса и статические методы. Фабрики аппетитной пиццы с @classmethod

    На этом шаге мы разберем еще один пример.

    Если вы сталкивались с пиццей в реальном мире, то вы знаете, что существует много видов аппетитной пиццы:

Pizza(['моцарелла', 'помидоры'])
Pizza(['моцарелла', 'помидоры', 'ветчина', 'грибы'])
Pizza(['моцарелла'] * 4)

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

    Хороший и очевидный способ это сделать - использовать методы класса в качестве фабричных функций для различных видов пицц, которые мы можем создать:


См. Википедию: «Фабрика (объектно-ориентированное программирование)»: https://en.wikipedia.org/wiki/Factory_(object-oriented_programming) и https://ru.wikipedia.org/wiki/Абстрактная_фабрика_(шаблон_проектирования)
>>> class Pizza:
	def __init__(self, ingredients):
		self.ingredients = ingredients
	def __repr__(self):
		return f'Pizza({self.ingredients!r})'
	@classmethod
	def margherita(cls):
		return cls(['моцарелла', 'помидоры'])
	@classmethod
	def prosciutto(cls):
		return cls(['моцарелла', 'помидоры', 'ветчина'])

    Обратите внимание на то, как используется аргумент cls в фабричных методах margherita() и prosciutto() вместо вызова конструктора Pizza непосредственно.

    Вы можете использовать эту идиому, чтобы следовать принципу "Не повторяйся" (DRY). Если в какой-то момент мы решим этот класс переименовать, нам не нужно будет помнить об обновлении имени конструктора во всех фабричных функциях.

    Итак, что же мы можем сделать с этими фабричными методами? Давайте их испытаем:

>>> Pizza.margherita()
Pizza(['моцарелла', 'помидоры'])
>>> Pizza.prosciutto()
Pizza(['моцарелла', 'помидоры', 'ветчина'])

    Как видите, фабричные функции можно использовать для создания новых объектов Pizza, которые сконфигурированы именно так, как мы хотим. Внутри они все используют одинаковый конструктор __init__() и просто обеспечивают краткую форму для запоминания самых разнообразных ингредиентов.

    Еще один способ взглянуть на это использование методов класса - понять, что они позволяют определять для своих классов альтернативные конструкторы.

    Python допускает всего один метод __init__() в классе. Использование методов класса позволяет добавлять столько альтернативных конструкторов, сколько потребуется. Это может сделать интерфейс ваших классов (до известной степени) самодокументирующим и упростит их использование.

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




Предыдущий шаг Содержание Следующий шаг