UMLクラス図の表記の一部について混乱しています。
Associationが何を意味するのか、私はよく知っています。 2つのクラスのインスタンス間の関係(1つのクラスのインスタンスが作業を実行するために2番目のクラスのインスタンスについて知る必要がある場合)は、関連関係です。関連付けは、クラスAがクラスBのインスタンスへの参照(フィールド)を持っていることを意味します。
ただし、AggregationおよびCompositionの矢印の意味を理解できません。私の混乱の一部は、これらの表記法の異なる定義に遭遇することによって引き起こされました。
Aggregation表記の2つの定義:
定義1: 2つのクラス間の集約表記は、クラスAのインスタンスが常に保持されますコレクションを保持クラスBのインスタンス(例:リスト、配列など)。
定義2: 2つのクラス間の集約リンクは、クラスAのインスタンスがクラスBのインスタンスへの参照を保持している場合に適していますそしてBインスタンスはAのライフサイクルに依存していますinstance。意味:クラスAのインスタンスが削除されると、クラスBのインスタンスも削除されます。クラスBのインスタンスは完全に含まれていますクラスAのインスタンスによって、クラスAのインスタンスは、通常の関連付けであるクラスBのインスタンスへの参照を所有しているだけです。
構成表記の意味と、それが集計表記とどのように異なるかについては、よくわかりません。
定義を明確にして、理解してください。具体的な例を歓迎します。
3つのリンクAssociation、Aggregation、Compositionは、2つのクラスが互いにどの程度密接に関連しているかについて一種の尺度を形成します。
スケールの一方の端には、2つのクラスのオブジェクトがお互いについて知ることができる関連がありますが、それらはお互いの存続期間に影響を与えません。オブジェクトは独立して存在することができ、どのクラスAオブジェクトはどのクラスBオブジェクトが時間とともに変化する可能性があるかを認識しています。
スケールの反対側には、構成があります。構成は、一部を表します-クラスBがクラスAの不可欠な部分であるような関係全体。この関係は通常、クラスBのオブジェクトがなければクラスAのオブジェクトが論理的に存在できない場合に使用されます。
アグリゲーションの関係は、これらの2つの端の間にあるものですが、正確にどこで合意するかは誰にもわからないため、アグリゲーションの意味について普遍的に合意された定義もありません。その意味で、あなたが見つけた両方の定義は正しいものであり、10人に尋ねると、11の異なる定義を取得するリスクがあります。
構成は、_object A
_に_object B
_が含まれ、_object A
_が_object B
_の作成も担当する場合です。
組成関係
クラスBで使用されるクラスAがあります。
_final class A
{
}
_
構成がどのように見えるかについては、複数のオプションがあります。
直接初期化構成:
_final class B
{
private $a = new A();
}
_
コンストラクタ初期化構成
_final class B
{
private $a;
public function __construct()
{
$this->a = new A();
}
}
_
遅延初期化構成
_final class B
{
private $a = null;
public function useA()
{
if ($this->a === null) {
$this->a = new A();
}
/* Use $this->a */
}
}
_
これにより、クラスA
とB
の間に密接な関係が作成されます。クラスB
は、A
なしでは存在できません。これは 依存性注入の原則 の重大な違反です。
依存関係は、使用できるオブジェクト(サービス)です。インジェクションとは、依存関係を使用する依存オブジェクト(クライアント)に依存関係を渡すことです。サービスはクライアントの状態の一部になります。クライアントがサービスを構築または検索できるようにするのではなく、サービスをクライアントに渡すことは、パターンの基本的な要件です。
PHPで_new DateTime
_を呼び出したり、C++で_new std::vector<int>
_を呼び出したりする場合など、合成は意味をなす場合があります。しかし、たいていの場合、これは警告であり、コード設計が間違っていることを示しています。
_class A
_がキャッシュに使用される特別なオブジェクトである場合、_class B
_は常に_class A
_の実装を使用してキャッシュされ、動的に変更するコントロールはありません。 、それは悪いです。
また、遅延初期化構成を使用した場合、つまり、useA()
メソッドと呼ばれる実際の_object B
_と_object A
_は失敗し、あなたの_object B
_は突然役に立たなくなります。
一方、集約は関係の方法であり、 DI原則 に従います。 _object B
_は_object A
_を使用する必要があります。次に、作成済みの_object A
_のインスタンスを_object B
_に渡し、_object A
_の作成に失敗した場合、何も渡されませんそもそも。
つまり、Aggregationは、依存性注入の原則のUML表現であり、コンストラクター注入、セッター注入、パブリックプロパティ注入のいずれであってもかまいません。
これらはすべてアグリゲーションです
最もタイトなコンストラクター注入(_object B
_は_object A
_なしでは存在できません)。
_final class B
{
private $a;
public function __construct(A $a)
{
$this->a = $a;
}
}
_
Looser(_object A
_内で_object B
_を使用しても使用しなくてもかまいませんが、使用する場合は、最初に設定する必要があります)。
セッター経由:
_final class B
{
private $a;
public function setA(A $a)
{
$this->a = $a;
}
}
_
公共施設経由:
_final class B
{
public $a;
}
_
使用しているすべてがクラスの具体的な実装である場合、CompositionよりもAggregationの使用を正当化する優れた方法は実際にはありませんが、インターフェイスの注入を開始すると、またはC++抽象クラスの場合、突然Aggregationが唯一の方法になります契約を履行します。
さらに、現在のUML標準の抜粋:
11.5.4関連付け–セマンティクス–表記
[...]バイナリアソシエーションは、aggregation = AggregationKind :: sharedまたはaggregate = AggregationKind :: compositeを片端に持つ場合があります。一端に集約がある場合(AggregationKind :: shared a hollow diamondが端末として追加されますAggregation = AggregationKind :: sharedでマークされた端の反対側のAssociation行の端にある装飾。ダイヤモンドは協会のダイヤモンド表記よりも著しく小さくなければならない。集計の関連付け= AggregationKind :: composite同様に、対応する端にダイヤモンドがありますが、diamond fillインチ[…]
9.5.4分類–プロパティ–表記
[…]プロパティは、1つのインスタンスを使用して一連のインスタンスをグループ化する状況をモデル化するために使用される場合があります。これは集約と呼ばれます。このような状況を表すために、プロパティにはAggregationKindタイプの集約プロパティがあります。グループ全体を表すインスタンスはプロパティの所有者によって分類され、グループ化された個人を表すインスタンスはプロパティのタイプによって分類されます。 AggregationKindは、次のリテラル値を持つ列挙です。
- none:プロパティに集約セマンティクスがないことを示します。
- 共有:プロパティが共有セマンティクスを共有していることを示します。共有集約の正確なセマンティクスは、アプリケーション領域とモデラーによって異なります。
- Composite:プロパティが複合的に集約されていることを示します。つまり、複合オブジェクトは、構成されたオブジェクトの存在と格納に責任を負います(11.2.3のパーツの定義を参照)。複合集計は強力な形式の集計であり、パーツオブジェクトを一度に最大で1つの複合オブジェクトに含める必要があります。複合オブジェクトが削除されると、オブジェクトであるそのすべての部品インスタンスも一緒に削除されます。
[…]
私はすでに Stackoverflowの回答 を投稿しました。
基本的に、集約は単純な関連付けよりも強力ですが、集約されたオブジェクトは、単純な関連付けの場合と同様に、お互いがなくても「生存」できます。
集約クラスは他のクラスによって集約できないため、合成は集約よりもさらに強力です。その「寿命」はコンテナに依存します。