返回已存在实例的Python抽象属性是否属于工厂模式?
先直接给结论:你的实现并不严格符合传统的工厂方法模式,但它是一种结合了抽象工厂思想和单例特性的实用设计,有明确的模式归类。
一、先明确工厂方法模式的核心(基于Refactoring Guru定义)
工厂方法定义一个用于创建对象的方法,替代直接调用构造函数,子类可重写该方法以改变创建的对象类型
这里的核心关键词是**「创建对象的方法」**:
- 方法的主要职责是实例化对象(不管每次是否生成新实例,核心动作是“创建”);
- 子类重写方法是为了决定创建哪种类型的对象,创建时机由调用方触发(比如调用
make_animal()时才执行创建逻辑)。
二、你的实现和传统工厂方法的差异
对比你的代码和传统示例就能看出核心区别:
传统工厂方法(创建导向)
class DogFactory(AnimalFactory): #override def make_animal(self) -> IAnimal: return Dog() # 每次调用都触发实例化(或按需缓存)
这里make_animal()是一个创建方法,调用它才会完成对象实例化,重点在“创建动作”本身。
你的实现(提供导向)
class DogFactory2(AnimalFactory2): def __init__(self): self.__dog = Dog() # 工厂初始化时就完成了实例创建 #override @property def animal(self) -> IAnimal: return self.__dog # 仅返回已存在的实例,无创建动作
你的animal属性是提供已存在实例的访问入口,实例在工厂初始化阶段就已创建完成,后续访问只是复用这个实例,重点在“复用”而非“创建”。
三、你的实现属于哪种模式?
你的实现可以看作以下两种模式的结合:
抽象工厂模式的简化变种
抽象工厂模式的核心是定义一个接口,用于封装一系列相关/依赖对象的创建;你的实现用抽象基类AnimalFactory2定义了“提供Animal实例”的契约,子类CatFactory2/DogFactory2负责提供具体类型的实例——这符合抽象工厂“抽象产品提供逻辑”的思想,只是你这里仅涉及单个产品类型。单例提供者模式
因为你在工厂初始化时就创建了唯一的实例,后续每次访问animal属性都返回同一个对象,这结合了单例模式的特性,目的是复用同一个实例(这也正好解决了你遇到的Observer模式回调失效问题:如果每次返回新实例,观察者订阅的就不是同一个对象,自然收不到回调)。
四、结合你的实际场景的合理性
回到你的CraneInterface场景:
你需要Crane的实现类(CraneSimulator、CraneOpcuaClient)提供AxisInterface的实例,并且这个实例要被多个观察者订阅——如果用传统工厂方法每次创建新实例,Observer模式的回调肯定会失效。而你的设计通过抽象属性返回预先创建好的单例实例,完美解决了这个问题,同时遵循了依赖倒置原则(CraneInterface依赖AxisInterface抽象,而非具体实现)。
这种设计是完全合理的,虽然不是严格的工厂方法模式,但属于实用的模式变种,在需要复用实例的场景下非常合适。
内容的提问来源于stack exchange,提问作者Blue7

