2

これらの関係を想像してみてください。

  • 1Aには多くのBがあります
  • 1Bには多くのCがあります。

逆に:

  • Cには1つのBがあります
  • Bには1Aがあります
  • 推移性により、Cは1Aを持ちます

DBでこの関係をモデル化するには、次のようにします。

TableA
a_id

TableB
b_id
a_id (fk to TableA)

TableC
c_id
b_id (fk to TableB)

OOでこの関係をモデル化するには、次のようにします。

objA
objB
objC

そして...--objBはobjAへの参照を持っています-objCはobjBへの参照を持っています

objCにobjAのメソッドを呼び出す必要のあるメソッドがある場合、どうしますか?

オプション1。

b.getA().runMethodX()

私が知っている多くのpplはこれを行うでしょうが、getA()は純粋なOOの意味でのBの動作ではないため、これは良くないことも学びました。そうすることは、手続き型プログラミングを行うのと同じです。同意する同意しません?

オプション2。

コンストラクターインジェクション/セッターを介してobjCがobjAとobjBを直接参照するようにします

これは良い考えですか?しかし、objCが参照しているobjBもobjAを参照しています。これで大丈夫ですか?または、循環オブジェクト参照の場合でない限り、それは許容されますか?

オプション3。

問題のメソッドをobjAに移動し、パラメーターでobjCを渡します。

これがオプションと見なされるかどうかはわかりません。すべての場合に機能するとは限りません。objCのメソッドを、その状態でのみ機能する最小限に減らし、objAが前後に実行する必要があることをすべて実行するようにします。

オプション4. (委任)

runMethodXinA()をBに追加すると、

a.runMethodX()

Cコール

b.runMethodXinA()

私は以前にこの方法を試しましたが、BはAと同じ数の方法を持っている可能性が高く、BとAの両方に1つの方法がない場合はDRYに違反しますか?

あなたは何ですか?他のオプションはありますか?コメント?提案?

4

5 に答える 5

2

オプション2は、環境によっては参照グラフの形状から生じる可能性のある問題に加えて、かなり危険な情報の複製です。

オプション3は、メソッドが何らかの意味でobjAのタイプに依存している場合、一種のダブルディスパッチとして意味をなす可能性があります。

オプション1はデメテルの法則に反しますが、最も邪魔にならないオプションのようです。

objAへの呼び出しを渡すobjBの転送メソッドを検討することもできます。

于 2009-02-19T03:42:14.053 に答える
0

状況に応じて1号または4号。私の金属切削ソフトウェアでは、オブジェクトの親/起源を知る必要がある多くのインスタンスがあります。たとえば、フィッティングにパス コレクションがあり、各パスにはそれを作成したフィッティングを返す Fitting プロパティがあります。

ただし、元のオブジェクトがその目的を達成するのに役立つという理由だけで接続されたオブジェクトが存在する場合 (数学のサポートなど)、委譲の方が適している可能性があります。

接続されたオブジェクトが元のオブジェクトを変更する場合は、ビジター パターンを使用したほうがよいでしょう。

唯一の注意点は、ほとんどの OOP では、二重にリンクされたオブジェクトに注意する必要があるということです。親子リンクが相互に接続されているオブジェクトでは、ガベージ コレクションが失敗することがよくあります。また、親子リンクのクリーンアップを忘れるのはよくある間違いです。

イベントの作成と消費をサポートする OOP を使用すると、この問題を回避できます。プロキシを使用する。親は子に、それ自体ではなくプロキシ オブジェクトを渡します。子が親を必要とする場合、プロキシ オブジェクトから参照を取得します。プロキシ オブジェクトは、親がそれ自体を返す原因となるイベントとして発生します。ハード リンクがないため、プログラマーまたはガベージ コレクターがクリーンアップしないという問題が軽減されます。

于 2009-02-19T13:14:21.697 に答える
0

問題は、どのようなモデルを使用するかだと思います。構造全体が事前にわかっていて、それが変わらないリレーショナル モデルを使用する場合は、オプション 1 を使用できます。つまり、特定の組織パターンの A のデータ/メソッドが C に必要です。

オプション 2 は良いアイデアのように思えるかもしれません。しかし、基本的に同じオブジェクトへの 2 つの参照を保存しています。B が別の A にマップされた場合、B は C にその参照も変更するよう通知する必要があります。ダメ。

ただし、オプション 4 は、真の OO アプローチの正しい方法のように思えます。ポイントは、A はその構造を変更でき、B を適応させるだけでよいということです。つまり、直接の子です。C は、A がどのように実装されているかを知りませんし、気にもしません。A が単に存在し、B がそれをどうするかを知っているだけで十分です。

于 2009-02-19T02:50:48.530 に答える
0

選択肢のリストから、デメテルの法則に従うため、選択肢はオプション 4 です。

  • オプション1はデメテルの法則に違反しています
  • オプション 2 は冗長な参照導入し、デメテルの法則に間接的に違反します
  • オプション 3 は、オブジェクト A をオブジェクト C の知識で汚染します。これは、おそらくデメテルの法則にも違反します (逆に)。

それはオプション4を残します

オプション5があるかもしれませんが、それは元の質問の範囲を超えています;-)

于 2009-02-19T02:48:51.793 に答える
0

C から B から A へのバック ポインターが実際に必要ですか、それとも C から A にアクセスできるようにするためだけに必要ですか? おそらく、A は B と C を作成し、それらの関係を管理する責任を負うべきです。そのシナリオでは、A は C を作成するときに C に自身を挿入できます (たとえば、C には A を受け取るコンストラクターがある場合があります)。

C が必要とする A 上の関数を分離し、そのためのインターフェイスを作成することもできます。インターフェイス (A ではなく) は、構築時に C に渡されます。これにより、C が A から切り離されます。

于 2009-02-19T03:24:47.620 に答える