Python工厂动态实例化

问题描述

我是C#程序员,并且我希望建立一个简单的工厂。遵守豁免规定:

class ShapeFactory:
    _registry: Dict[ShapeType,Shape] = {
        ShapeType.Shape: lambda: Shape(),ShapeType.Circle: lambda: Circle(),ShapeType.Square: lambda: Square()
    }

    def Create(self,key: ShapeType) -> Shape:
        if key in self._registry:
            return self._registry.get(key)
        raise KeyError(key)

    def Register(self,key: ShapeType,value: Shape) -> None:
        if key not in self._registry:
            self._registry[key] = value
        raise KeyError(type)

问题在于Create将始终返回Circle的相同实例。如何在允许OCP的同时实现一种动态实例化对象的方法

编辑: 进一步说明我的观点;在C#中,我将我的字典声明为:

Dictionary<ShapeType,Func<Shape>> _registry = new Dictionary{
    [ShapeType.Shape] = () => new Shape(),[ShapeType.Circle] = () => new Circle(),[ShapeType.Square] = () => new Square()
}

这将始终为字典的每个值返回一个新实例化的对象。这是我希望在python中重现的效果

解决方法

您在设计中遇到了一些较大的问题。

首先,如果您在类中具有可变属性,则应在类的_registry方法(与实例隔离)中定义__init__

接下来,_registry的type属性错误。您有dict的{​​{1}},而不是lambda的实例。您需要ShapeDict[ShapeType,Callable[[],Shape]]方法有一个类似的问题。

您还应该遵循PEP 8命名规则。试试这个:

Register
,

动态创建对象的一种简单的Python方法是:

class C:
    def __init__(self):
        self.name = "C"
class D:
    def __init__(self):
        self.name = "D"

dic = {"C": C,"D": D}
x1 = dic["C"]()
x2 = dic["C"]()
print(x1 is x2)    #prints False