Python设计模式:嵌套抽象类

7
在以下示例代码中,我希望每个car对象都由存储为汽车属性的brake_systemengine_system对象组成。
为了实现这一点,我已经将CarBreakSystemEngineSystem定义为抽象类。每个Car子类都需要将其相应的BreakSystemEngineSystem子类定义为类属性。
这种方法是否存在潜在问题?或者有其他更适合处理嵌套抽象的设计模式吗?
from abc import ABC, abstractmethod

class Car(ABC):
    """
    every car object should have an Engine object and a BrakeSystem object
    """

    def __init__(self):
        self.engine_system = self._engine_type()
        self.brake_system = self._brake_type()

    @property
    @abstractmethod
    def _engine_type(self):
        raise NotImplementedError()

    @property
    @abstractmethod
    def _brake_type(self):
        raise NotImplementedError()

class EngineSystem(ABC):
    pass

class BrakeSystem(ABC):
    pass


class FooBrakeSystem(BrakeSystem):
    pass

class FooEngineSystem(EngineSystem):
    pass

class FooCar(Car):
    _engine_type = FooEngineSystem
    _brake_type = FooBrakeSystem

if __name__ == '__main__':
    obj = FooCar()

这个问题本身并没有什么大问题,但为什么要在这里使用ABC呢?为什么ABC,通常用于记录公共API,要关注汽车的实现细节呢?发动机和刹车类型是公共API信息吗? - Martijn Pieters
这不是ABC的典型用例吗?我们只想让car类通过其子类进行初始化,因此我们将其设置为ABC。虽然我没有编写公共API,但我经常使用ABC来组织相关类的层次结构。 - donghyun208
1
不,这不是典型的用法。ABCs 更常用于帮助第三方开发人员理解在实现特定“协议”时必须提供什么,即一组在类上定义行为模式的方法集。请查看 collections.abc 模块以获取 Python 容器行为的定义。一个 Mapping 类的内部实现可能并不重要,只要它实现了 ABC 的抽象方法,其他代码就可以依赖它具有所有正确的方法。 - Martijn Pieters
2个回答

8

我希望每个汽车对象由刹车系统发动机系统对象组成。

你已经有了系统的抽象类。

class EngineSystem(ABC):
    pass

class BrakeSystem(ABC):
    pass

汽车必须包含两个系统:

class Car:

    def __init__(self, engine: EngineSystem, brake: BrakeSystem):
        self._engine_system = engine
        self._brake_system = brake

    @property
    def engine_type(self) -> EngineSystem:
        return self._engine_system

    @property
    def brake_type(self) -> BrakeSystem:
        return self._engine_system

如果您需要创建一个特定的汽车

tesla = Car(ElectroEngine(), Disks())

# or even 
class Tesla(Car):
    def __init__(self):
        super().__init__(ElectroEngine(), Disks())

tesla = Tesla()

这种方法允许您将car作为其系统的组合创建。


1
小注释:在 def brake_type 中,我认为 return 应该是 self._brake_system(?) - Alex S.

0

我是Python的初学者。

根据面向对象的概念回答你的问题,嵌套抽象类以强制实现者定义外部类所封装的内容是完全可以的。我没有看到这种结构存在任何潜在问题。

在你的例子中,当一个人需要将真实世界的实体模拟成软件时,Car具有BreakSystemEngineSystem是非常合理的,同时所有这些都非常通用,因此将它们作为抽象类是可以接受的,并让实现者在具体类中定义细节。

如果你使用组合,也可以模拟这个过程,例如,一个人可以将建筑物和房间作为抽象类型(其中建筑物由房间组成),并使用Flat/House来实现,其中House/Flat有像餐厅和/或客厅等房间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接