6

一連の包括的な属性を持つ製品をモデル化しようとしています。通常、オンライン ストアではテキストの説明を使用して、特定の製品の属性を一覧表示します。ただし、このソリューションは最適ではありません。

たとえば、次のリンクは、同じ製品のテキスト説明内の属性の不一致を示していますが、メーカーは異なります。

したがって、次のような継承階層を選択しました。

Product> Component> GraphicsCard>NvidiaGraphicsCard

この理由は、各 の属性をきめ細かく制御したいからですProductNvidiaGraphicsCardこれにより、 aには適用されないa に固有の属性を含めることができますATiGraphicsCard

サブクラスにフィールドを追加するだけでなく、継承により、OrderItema への参照を保持するという点でポリモーフィズムを利用できることに注意してくださいProduct。これが、合成を除外した理由です。

このような深い継承階層を持つことに問題はありますか?もしそうなら、この問題を処理するための解決策やパターンはありますか?

4

3 に答える 3

8

深い継承階層は、いくつかの理由から、DDD および ORM のコンテキストでは問題があります。エンティティの ID を定義しようとすると、1 つの問題が発生します。Productどのサブクラスを比較するかに関係なく、同一性に基づいて他の製品と比較できる必要があります。この機能はProductクラスで提供できますが、サブクラスも比較できるように注意する必要があり、いくつかの落とし穴があります。たとえば、NHibernate はクラスのプロキシを生成するため、オブジェクトの実際の実行時の型は、NvidiaGraphicsCardそれを継承するプロキシになります。の一時的なインスタンスはNvidiaGraphicsCardプロキシにはなりません。つまり、タイプに基づいてそれらを比較することはできません。

もう 1 つの問題は、継承をサポートするように ORM マッピングを構成することです。ほとんどの ORM ではそれが可能ですが、結果のマッピングと生成された SQL は複雑になることがよくあります。すべてのサブクラスを 1 つのテーブルに格納しますか? 共通の製品テーブルへの外部キーを持つ複数のテーブルで? 前者では、巨大なテーブルになってしまいます。後者の場合、すべてのサブクラス テーブルを結合する必要があるため、クエリに問題が生じます。リレーショナル モデルとオブジェクト モデルの間のインピーダンスの不一致が大きすぎます。文書データベースを使用している場合は、継承よりも構成を優先するのが最善です。

Product代わりに、製品固有の記述子または属性のディクショナリのいずれかで構成できる単一のクラスを使用します。これは、特定の製品タイプを知らなくてもOrderItem参照できます。ポリモーフィズムは必要ありません。Productこれにより、新しいタイプの製品を簡単に許可できるようになります。新しいサブクラスを作成する必要はありません。

于 2012-10-13T21:07:47.970 に答える
1

これは継承の教科書の例であり、良い例です。リレーショナル データベースに永続化するのが難しいことを除けば、このようなモデルに問題はないと思います。

一方、プロパティのグループは、単一の継承では表現できないアイテムのサブセットにのみ関連する場合があります。たとえばPowerConsumption、特定の製品に必要な電力量を説明することは、マウスや USB スティックには関係ありません。また、一部のコンポーネントでは重量はそれほど重要ではありません。つまり、Scala などの特性を持つ言語を調査して、モデルを可能な限り DRY にすることができます。

深い継承によるパフォーマンスの低下はないことに注意してください。継承チェーンが長くなっても、仮想メソッドの呼び出しが遅くなるわけではありません (これらは単なるデータ コンテナーであるため、仮想呼び出しはあまり使用しません)。

于 2012-10-11T19:25:07.283 に答える
0

Decorator パターンを参照することをお勧めします。このようにして、必要なフィネスと 10 億未満のクラスが得られます。

于 2012-10-11T19:34:25.167 に答える