问题背景:
组合和聚合这两个术语来源于经典的面向对象设计。它们描述了对象之间的关系:“整体–部分”,但在对象的关联程度上有所不同。
问题:
在大型系统中,代码的可读性和可扩展性非常重要。组合和聚合有助于建立类之间的合理依赖。理解它们之间的区别是很重要的,否则可能会导致架构过于僵化或模糊。
解决方法:
组合 — 这是强的“部分-整体”关系。当一个对象仅存在于另一个对象内部,并且不能在外部存在时。在 Python 中,这样的对象通常在“容器”类中创建和管理。
聚合 — 这是较弱的关系。对象“部分”可以独立于对象“整体”存在,并且可以从外部传递到它里面。
代码示例:
class Engine: def start(self): print("发动机启动") class Car: # 组合:在 Car 中创建 Engine def __init__(self): self.engine = Engine() def drive(self): self.engine.start() my_car = Car() my_car.drive() class Wheel: pass class Bicycle: # 聚合:轮子从外部传递 def __init__(self, wheels): self.wheels = wheels w1, w2 = Wheel(), Wheel() bike = Bicycle([w1, w2])
关键特点:
如果删除“容器”对象(例如 Car),那么 Engine 对象是否会被删除?
在组合中,如果没有其他对象引用“部分”对象,它将被垃圾收集器删除。而在聚合中,“部分”对象仍然可以存在(其他对象可能仍然引用它)。
Python 中是否有专门的语法用于聚合和组合,像其他语言那样?
在 Python 中没有明确指示组合/聚合的关键字。一切都取决于对象的创建和生命周期管理方法。
可以不重写逻辑将组合更改为聚合,反之亦然吗?
并非总是如此。如果逻辑需要对“部分”对象的完全控制和唯一性,简单地将组合替换为聚合可能会导致错误(例如,如果不同自行车的轮子变成同一类的共享实例)。
优点:
负面案例:在项目中,为每辆汽车创建了一个外部引擎对象,并通过聚合传递到汽车中。然而,之后搞混了对象的引用,并随意更换了汽车之间的引擎——这导致了混乱和缺陷。
优点:架构看起来很灵活。 缺点:很难弄清楚哪个引擎属于哪辆汽车。
积极案例:在另一个项目中,发动机在 Car 类内部创建(组合);汽车直接管理自己的发动机,这确保了可靠性。
优点:没有泄漏和逻辑混淆。 缺点:需要编写更多代码来管理每辆汽车及其细节的生命周期。