背景:
コンポジションとアグリゲーションという用語は、従来のオブジェクト指向設計から来ており、オブジェクト間の関係を説明します:「全体-部分」の関係ですが、オブジェクトの関連性の程度によって異なります。
問題:
大規模なシステムでは、コードの可読性と拡張性が重要です。コンポジションとアグリゲーションは、クラス間の適切な依存関係を構築するのに役立ちます。その違いを理解することが重要です — さもなければ、アーキテクチャがあまりにも堅固になったり、逆にあいまいになったりする可能性があります。
解決策:
コンポジション — 強い「部分-全体」の結びつきです。オブジェクトが他のオブジェクトの内部にのみ存在し、それ以外では存在できない場合です。Pythonでは、そのようなオブジェクトは通常、"コンテナ"クラス内で作成され、管理されます。
アグリゲーション — より弱い結びつきです。"部分"オブジェクトは"全体"オブジェクトから独立して存在でき、外部から渡されることができます。
コード例:
class Engine: def start(self): print("エンジンが始動しました") class Car: # コンポジション: EngineをCarの内部で作成 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クラス内に作成され(コンポジション)、車両は直接エンジンを管理し、信頼性が確保されました。
利点: 漏れや論理的混乱がない。 欠点: 各車両とその部品のライフサイクルを管理するために、少し多くのコードを書く必要がありました。