【问题标题】:Python design patterns: Nested Abstract ClassesPython 设计模式:嵌套抽象类
【发布时间】:2018-09-18 01:33:21
【问题描述】:

在下面的示例代码中,我希望每个car 对象都由brake_system 和engine_system 对象组成,它们作为属性存储在汽车上。

为了实现这一点,我将Car、BreakSystem 和EngineSystem 定义为抽象类。 Car 的每个子类都需要将其各自的BreakSystem 和EngineSystem 子类定义为类属性。

这种方法有什么潜在的问题吗?还是有其他更适合处理嵌套抽象的设计模式?

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?为什么通常用于记录公共 API 的 ABC 应该关注汽车的实现细节?引擎和刹车类型是公共 API 信息吗?
  • 这不是 ABC 的典型用例吗?我们只希望 car 类通过其子类进行初始化,因此我们将其设为 ABC。我还没有编写公共 API,但我仍然经常使用 ABC 来组织相关类的层次结构。
  • 不,这不是典型的用途。 ABC 更常用于帮助第三方开发人员了解他们在实现特定“协议”时必须提供的内容,该协议是类上的一组方法,它们共同定义了一种行为模式。查看 collections.abc 模块以了解 Python 容器行为的定义。 Mapping 类的内部实现是什么并不重要,只要它实现了 ABC 的抽象方法,其他代码就可以依赖它来拥有所有正确的方法。

标签: python-3.x oop design-patterns abstract-class


【解决方案1】:

我希望每个汽车对象都由 brake_system 和 engine_system 对象组成

你有系统的抽象类

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 作为其系统的组合。

【讨论】:

  • 次要评论:在 def 刹车类型中我相信返回应该是 self._brake_system (?)
【解决方案2】:

我是python的初学者。

根据 OO 概念回答您的问题,嵌套抽象强制实现者必须定义外部类封装的内容是完全可以的。而且我看不出这个结构有任何潜在的问题。

在您的示例中,Car 具有 BreakSystem 和 EngineSystem 在必须将真实单词实体模拟为软件并且同时所有实体都非常通用的情况下非常有意义,因此将它们作为抽象是可以接受的并让实现者在具体类中定义细节。

如果你有组合,这也可以模拟,示例可以将 Building 和 Room 作为抽象类型(其中 Building 由 Room 组成),并且使用 Flat/House 可以在其中实现 House /Flat 有 DiningRoom 和/或 DrawingRoom 等房间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多