You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于Python工厂方法与抽象类的疑问:对网站代码示例的困惑

关于Python工厂方法模式实现的疑问解答

首先先把你贴出的代码放在这里方便参考:

class Shape(object): 
    # Create based on class name: 
    def factory(type): 
        #return eval(type + "()") 
        if type == "Circle": 
            return Circle() 
        if type == "Square": 
            return Square() 
        assert 0, "Bad shape creation: " + type 
    factory = staticmethod(factory) 
class Circle(Shape): 
    def draw(self): 
        print("Circle.draw") 
    def erase(self): 
        print("Circle.erase") 
class Square(Shape): 
    def draw(self): 
        print("Square.draw") 
    def erase(self): 
        print("Square.erase")

接下来分两部分解答你的疑问:

一、这段代码是否正确实现了工厂方法模式?

严格来说,它更接近简单工厂模式(也叫静态工厂模式),而非GoF定义的标准工厂方法模式。

先明确两者的核心区别:

  • 标准工厂方法模式的核心是:定义一个抽象工厂类,声明一个创建产品的抽象方法,然后由具体的工厂子类去实现这个方法,各自负责创建对应的产品实例,把类的实例化延迟到子类。
  • 而你的这段代码是在父类Shape中用一个静态方法factory集中处理了所有产品的创建逻辑,通过分支判断返回不同的子类实例。客户端只需要调用Shape.factory("Circle")就能拿到对应的对象,确实实现了对象创建与使用的解耦,但不符合标准工厂方法模式的“子类负责实例化”的核心要求。

不过如果从广义的“工厂封装对象创建”的角度来看,它确实达到了工厂模式的基本目的——让客户端不用直接和具体产品类耦合。

二、与抽象类设计的契合度如何?

契合度比较低,原因如下:

  1. 你代码中的Shape只是一个普通的父类,没有定义抽象方法来约束子类的行为。比如draw和erase方法应该是所有形状必须实现的核心行为,但现在如果新增一个Triangle子类却忘记实现这两个方法,只有在运行时调用这些方法才会报错,无法提前发现问题。
  2. 在Python中,我们可以通过abc模块来实现抽象类,强制子类必须实现指定的抽象方法,这样能保证所有子类都遵循统一的接口规范。

这里给你一个改进后的版本,加入抽象类的约束:

from abc import ABC, abstractmethod

class Shape(ABC):
    # 定义抽象方法,强制子类实现
    @abstractmethod
    def draw(self):
        pass
    
    @abstractmethod
    def erase(self):
        pass

    # 保留静态工厂方法
    @staticmethod
    def factory(type):
        if type == "Circle":
            return Circle()
        if type == "Square":
            return Square()
        raise ValueError(f"Bad shape creation: {type}")

class Circle(Shape):
    def draw(self):
        print("Circle.draw")
    def erase(self):
        print("Circle.erase")

class Square(Shape):
    def draw(self):
        print("Square.draw")
    def erase(self):
        print("Square.erase")

这个版本中,Shape作为抽象基类,任何继承它的子类必须实现draw和erase方法,否则在定义子类时就会抛出错误,能更早地发现接口不一致的问题,也更符合抽象类设计的初衷。

内容的提问来源于stack exchange,提问作者Randomizer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:39:41