Skip to main content
 首页 » 编程设计

python之如何实现一个工厂类

2025年05月04日9zengkefu

我希望能够基于枚举类创建对象,并使用字典。像这样:

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 BakedBeans(Ingredient): 
    pass 
class Egg(Ingredient): 
    pass 
 
 
class IngredientFactory(object): 
    """Factory makes ingredients""" 
 
    choice = { 
        IngredientType.SPAM: IngredientFactory.MakeSpam, 
        IngredientType.BAKED_BEANS: IngredientFactory.MakeBakedBeans, 
        IngredientType.EGG: IngredientFactory.MakeEgg 
    } 
 
    @staticmethod 
    def make(type): 
        method = choice[type] 
        return method() 
 
    @staticmethod 
    def makeSpam(): 
        return Spam() 
 
    @staticmethod 
    def makeBakedBeans(): 
        return BakedBeans() 
 
    @staticmethod 
    def makeEgg(): 
        return Egg() 

但是我得到了错误:

NameError: name 'IngredientFactory' is not defined 

由于某种原因无法创建字典。 我哪里出错了?

请您参考如下方法:

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 dict疯狂物理学家:

# 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) 

但我也真的看不到这里有任何好处

编辑:你提到:

I am trying to implement the factory pattern, with the intent of hiding the creation of objects away. The user of the factory then just handles 'Ingredients' without knowledge of the concrete type

用户仍然必须指定他想要什么样的配料(ingredient_type 参数)所以我不确定我是否理解这里的好处。您的真实用例实际上是什么? (编造/简化示例的问题在于它们并没有讲述整个故事)。