オブジェクトが物理的に存在するかどうかに関係なく、さまざまな方法でモデル化することができます。多くの場合、一般化または合成を任意に使用できます。ただし、「一般化よりも構成を優先する」というGoFの原則により、構成を使用するようにガイドされます。したがって、たとえば線をモデル化する場合、Point(一般化)を拡張する代わりに、Point(構成)タイプの2つのメンバーPointAおよびPointBを含むクラスを作成します。これは、オブジェクトが通常ははるかに複雑であるにもかかわらず、モデル化するための構成または継承を任意に選択できる方法の単純化された例にすぎません。
これが正しい選択であることをどのように知ることができますか?少なくとも、それが間違っている場合は大量のリファクタリングが必要になる可能性があるため、問題になりますか?
常に正しい選択ではありません。ほとんどの場合favourable 1です。複合モデルが変更または拡張を必要とする場合、他のクラスに不注意に影響を与えることを恐れずに構成を変更できるため、それに対してかなり抵抗力があります。
これをどうやって知るのですか?経験から、そして他人の経験から。
単純な概念として始まったものから大規模なクラス階層が成長した多くの状況を見てきましたが、ここで大きなリファクタリングが必要になります。その間、私は合成構造が継承へのリファクタリングを必要とする状況を見たことがありません。
しかし、私の事例証拠は十分ではありません。インターネットを見回すだけで、かなりの数の人が同じ経験をしました。
「継承よりも構成を優先する」を超えたより強力な経験則が必要な場合は、次のようなものをお勧めします。
オブジェクトを特殊化する2つの方法-継承と構成-は、特殊化する基本クラスに対してオブジェクトを多態性(置換可能)にする必要がある場合にのみ、継承を使用する必要があります。
ただし、すべての経験則と同様に、いったんルールを理解すると、ルールを自由に破ることができます。
構成と一般化がどのように選択肢であるか、そして 引用を見つけることができませんでした がわかりません。
構成と継承は(特殊化を実現するため)であり、抽象化と一般化は(モジュール化を実現するため)であると主張できます。
必要なのは、デザインをシンプルでもっともらしいものにすることです。これは、本質的に非常に簡単に測定できる2つの品質です。
あなたの場合、点の概念を拡張するのではなく、自然に2点で線を定義するので、2点の線を拡張するのではなく、構成するほうがもっともらしいようです。
両方の候補者が適格である場合に有利になります。質問に述べられている問題は、構成オプションしかないため、このアカウントでは失敗します。
「組成も汎化を使用できます」。このステートメントは私たちにとって意味がありますか?そうでない場合、「有利な」ルールを把握する準備がまだできていません。
コンポジションを支持する理由は、コンポジションが一般化よりも多くの拡張/柔軟性の可能性を提供することです。この拡張/柔軟性は、主にランタイム/動的柔軟性を指します(これは、インターフェースと構成の組み合わせによって実現されます)。
メリットはすぐにはわかりません。メリットを確認するには、次の予期しない変更リクエストを待つ必要があります。そのため、ほとんどの場合、一般化にこだわった人は、構成を採用した人と比較すると失敗します(後述する明らかな1つのケースを除く)。したがって、ルール。学習の観点から、依存性注入を正常に実装できる場合は、どちらをいつ使用するかを知る必要があります。このルールは、どちらを選択すればよいかわからない場合の決定に役立ちます。ここでも、どちらか一方を優先するために、最初に両方のオプションを表示できるはずです。
概要:構成:小さなものを大きなものに接続するだけで結合が減少し、大きなオブジェクトは小さなオブジェクトをコールバックするだけです。ジェネラライゼーション:メソッドをオーバーライドできることを定義するサードパーティAPIの観点からは、メソッドを呼び出すことができると定義するよりも強い責任があります(一般化には確実に有利です)。また、構成では、大きなクラスの代わりにインターフェースから一般化も使用していることを忘れないでください。しかし、残念ながらクレジット全体は作曲に使用されます。