Python не является Java и не требует, чтобы все было в классе.Здесь у вашего IngredientFactory
класса нет состояний и только статические методы, так что на самом деле это просто одноэлементное пространство имен, которое в Python канонически выполняется с использованием модуля в качестве одноэлементного пространства имен и простых функций.Также, поскольку классы Python уже доступны для вызова, перенос экземпляра в функцию не имеет смысла.Простая и понятная реализация pythonic будет выглядеть так:
# ingredients.py
class IngredientType(Enum):
SPAM = auto() # Some spam
BAKE_BEANS = auto() # Baked beans
EGG = auto() # Fried egg
class Ingredient(object):
pass
class Spam(Ingredient):
pass
class Beans(Ingredient):
pass
class Egg(Ingredient):
pass
_choice = {
IngredientType.SPAM: Spam,
IngredientType.BAKED_BEANS: Beans,
IngredientType.EGG: Egg
}
def make(ingredient_type):
cls = _choice[ingredient_type]
return cls()
И код клиента:
import ingredients
egg = ingredients.make(ingredients.IngredientType.EGG)
# or much more simply:
egg = ingredients.Egg()
FWIW перечисление IngredientType
не приносит здесь много, и даже делает вещи болеесложно, что они должны быть - вы могли бы просто использовать простые строки:
# ingredients.py
class Ingredient(object):
pass
class Spam(Ingredient):
pass
class Beans(Ingredient):
pass
class Egg(Ingredient):
pass
_choice = {
"spam": Spam,
"beans": Beans,
"egg": Egg
}
def make(ingredient_type):
cls = _choice[ingredient_type]
return cls()
и код клиента:
import ingredients
egg = ingredients.make("egg")
Или, если вы действительно хотите использовать Enum
, выможет, по крайней мере, избавиться от диктата choices
, используя сами классы в качестве значений для перечисления, как предложено MadPhysicist:
# ingredients.py
class Ingredient(object):
pass
class Spam(Ingredient):
pass
class Beans(Ingredient):
pass
class Egg(Ingredient):
pass
class IngredientType(Enum):
SPAM = Spam
BEANS = Beans
EGG = Egg
@staticmethod
def make(ingredient_type):
return ingredient_type.value()
и клиентский код
from ingredients import IngredientType
egg = IngredientType.make(IngredientType.EGG)
Но яна самом деле здесь тоже нет никакой пользы
EDIT: вы упомянули:
Я пытаюсь реализовать фабричный шаблон с намерением скрыть создание объектов.Затем пользователь фабрики просто обрабатывает «Ингредиенты», не зная о конкретном типе
Пользователь все еще должен указать, какие ингредиенты ему нужны (аргумент ingredient_type
), поэтому я неуверен, что я понимаю выгоду здесь.Какой у вас реальный вариант использования на самом деле?(проблема с вымышленными / глупыми примерами заключается в том, что они не рассказывают всю историю).