如何遵循开闭原则重构Python停车场Building类的__init__方法
解决方案
要实现符合开闭原则的设计,核心是把Size枚举与对应的Spot子类建立关联,让Building的初始化逻辑无需依赖硬编码的枚举判断。以下是两种可行的改造方式:
方式一:给Size枚举添加关联类属性
直接在枚举成员中绑定对应的Spot子类,通过自定义枚举的__new__方法让每个枚举实例携带车位类信息:
from enum import Enum class Size(Enum): SMALL = 1, SmallSpot MEDIUM = 2, MediumSpot LARGE = 3, LargeSpot def __new__(cls, value, spot_class): obj = object.__new__(cls) obj._value_ = value obj.spot_class = spot_class # 绑定对应的车位类 return obj class Spot: def __init__(self, id) -> None: self.id = id self.vehicle = None class SmallSpot(Spot): pass # 无额外逻辑可简化写法 class MediumSpot(Spot): pass class LargeSpot(Spot): pass class Building: def __init__(self, dic: dict[Size, int]) -> None: # 用统一字典存储所有类型的车位列表,避免零散的实例变量 self.spot_groups = {} for size, count in dic.items(): # 直接通过枚举获取对应车位类,生成实例列表 self.spot_groups[size] = [size.spot_class(i) for i in range(count)] # 如果需要兼容原有代码的small_spot_list等属性,可额外赋值 self.small_spot_list = self.spot_groups.get(Size.SMALL, []) self.medium_spot_list = self.spot_groups.get(Size.MEDIUM, []) self.large_spot_list = self.spot_groups.get(Size.LARGE, [])
方式二:维护枚举与车位类的映射字典
如果不想修改枚举的构造逻辑,可以单独维护一个映射字典,将Size枚举与Spot子类一一对应:
from enum import Enum class Size(Enum): SMALL = 1 MEDIUM = 2 LARGE = 3 class Spot: def __init__(self, id) -> None: self.id = id self.vehicle = None class SmallSpot(Spot): pass class MediumSpot(Spot): pass class LargeSpot(Spot): pass # 维护枚举与车位类的映射,新增类型时只需在这里添加条目 SIZE_SPOT_MAP = { Size.SMALL: SmallSpot, Size.MEDIUM: MediumSpot, Size.LARGE: LargeSpot } class Building: def __init__(self, dic: dict[Size, int]) -> None: self.spot_groups = {} for size, count in dic.items(): spot_class = SIZE_SPOT_MAP[size] self.spot_groups[size] = [spot_class(i) for i in range(count)] # 兼容原有属性(可选) self.small_spot_list = self.spot_groups.get(Size.SMALL, []) self.medium_spot_list = self.spot_groups.get(Size.MEDIUM, []) self.large_spot_list = self.spot_groups.get(Size.LARGE, [])
改造优势
- 新增停车位类型时,只需要:
- 新增一个继承自Spot的子类(如
XLargeSpot) - 在Size枚举中添加对应成员(方式一),或在映射字典中添加条目(方式二)
- 新增一个继承自Spot的子类(如
- 完全无需修改Building类的
__init__方法,符合开闭原则(对扩展开放,对修改关闭) - 用统一字典管理车位列表,后续查询、操作不同类型车位时更灵活
内容的提问来源于stack exchange,提问作者Hangji He
相关产品推荐
相关产品推荐

