Python 工厂动态实例化

Python factory dynamic instantiation

我是一名 C# 程序员,我正在寻找一个简单的工厂。观察appempt:

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 总是 return 同一个实例,比如说 Circle。如何在允许 OCP 的情况下实现动态实例化对象的方法?

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

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

这将始终return 为字典的每个值创建一个新实例化的对象。这是我希望在 python.

中重现的效果

动态创建对象的一种简单的 pythonic 方式是:

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

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

首先,如果你在 class 中有一个可变属性,你应该在 class 的 __init__ 方法中定义 _registry(与实例隔离) .

接下来,_registry的类型属性是错误的。您有 dictlambda 个实例,而不是 Shape 个实例。你需要 Dict[ShapeType, Callable[[], Shape]]Register方法也有类似的问题。

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

class ShapeFactory:
    def __init__(self) -> None:
        self._registry: Dict[ShapeType, Callable[[], 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[key]()
        else:
            raise KeyError(key)

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