2

集約と構成を使用してシミュレーション用のエンティティを作成しています。

次の C++ の例では:

class CCar
{
    CCar( CDriver* pDriver )
    { m_pDriver = pDriver; }

    CDriver* m_pDriver;

    CEngine m_Engine;

    CDriverControls m_Controls;
};

上記の例では、車はエンジンと一連の運転制御装置 (構成による) で構成されています。車にはドライバーも必要です (集計による)。

しかし、これは階層関係を説明するだけです。ドライバーは車に属し、エンジンとコントロールも車に属します。しかし、これらのメンバーはすべて互いに関連しています。ドライバーはコントロールでアクションを実行する必要があり、コントロールはエンジンでアクションを実行する必要があります。これらの関係は複数の方向にも作用します。エンジンが失速してコントロールが動かなくなったり、コントロールが乱暴にスピンしてドライバーを傷つけたりする可能性があります。また、ドライバーがエンジン音が気に入らず、車から離れたらどうしますか? これらの関係はどのように機能しますか?

私は、他のオブジェクトと頻繁に相互作用する多くの異なるオブジェクトから多くの異なるエンティティを合成しており、これらの関係を設計された方法で管理する方法に興味があります。

ありがとう!

編集:

回答が示唆するように、これを管理する 1 つの方法は、車をドライバーに向けたり、ドライバーに車へのポインターを提供したりすることです。これは理にかなっていて、この特定の例を解決します。ただし、設計上の意味では、これはドライバーの責任を増大させます。このオブジェクトは、どの車に属しているかを追跡する役割を担っていますが、確かにこれは、どのオブジェクトが一緒に属しているかを追跡するコンテナの義務なのでしょうか? 同様に、これらの関係の管理を CCar に任せると、CCar がブロブになります。この種の関係に対処するための設計されたソリューションはありますか?

4

5 に答える 5

1

構成、集約、または継承ではなく、インターフェースを強調すると便利な場合があります。たとえば、ドライバークラスは、「ステアリングホイール」インターフェイスを使用できるように作成できます。当然、ステアリングホイールの実装は、「ステアリングホイール」インターフェイスの実装を提供します。同様に、車は、ステアリングホイールの実装が利用できるように記述できる「車のインターフェース」を提供します。

実装では、構成、集約、および継承を使用できます。しかし、このアプローチでは、実際に設計を推進するのはインターフェースです。特定のインスタンスで構成、集約、または継承のいずれを使用するかは、単に実装の詳細になります。

于 2009-06-01T02:56:02.213 に答える
1

問題は、「私のアプリケーションにはこの関係が必要ですか?」ということです。たとえば、単純なドライビングゲームで車のステアリングをモデル化する場合、サンルーフのモーターについてはまったく心配する必要はありません。ステアリングホイールは、ロードホイールに接続されていることを知る必要があるかもしれませんが、逆の関係は必要ありません。

結論-現実の世界ではすべてがつながっていますが、特定の問題を解決するためにその世界で作成したコンピューターモデルでは、そうではありません。

于 2009-05-31T17:02:27.933 に答える
1

それらを各クラスのメソッドに組み込みます。あなたが説明しているのは、各クラスの動作です。あなたの要件は、関係が双方向であることも示唆しています。Controls クラスには、Engine パラメーターを受け取り、そのメソッドを呼び出すメソッドがあります。エンジンには、コントロールによって操作される RPM、HP、トルクなどに制限があり、制限が組み込まれています (たとえば、「RPM が低すぎる場合は失速します」)。

それは単なる構成以上のものです。ビルド動作とルールをメソッドに組み込みます。メソッドは、必要なものを表現するパラメーターを取る場合があります。

于 2009-05-31T16:55:02.310 に答える
0

この問題を解決するには、まず各コンポーネントが何をするのかを確立することが重要です。

CCar - コンポーネントと集合体を保持するコンテナ。

CDriver - ドライバーを表すオブジェクト

CEngine - エンジンを表すオブジェクト

小さくて単純なプログラムの場合、ドライバーに車へのポインターが与えられる単純化された設計を使用する必要があります。

CCar( CDriver* pDriver )
{
m_pDriver = pDriver;
m_pDriver->SetCar(this);
}

大規模なアプリケーションでは、CCar に新しいコンポーネントの追加などが必要になる可能性がある場合、これは受け入れられません。また、ドライバーが CCar 全体にアクセスできるようにすることは、設計上の不適切な方法です。ここでは、ドライバーはハンドルだけでなく、車の色などは明らかに意図したものではありません。

ドライバーが必要なビットにアクセスできるようにするだけではどうでしょうか?

m_pDriver->SetSteeringWheel( m_SteeringWheel );
m_pDriver->SetHandBrake( m_HandBrake );

これにより、その問題が解決され、ドライバーは車の他の属性 ( color など) にアクセスできなくなります。ただし、CDriver クラスにより多くの責任が与えられます。CDriver が多くのコントロールを使用できる場合、クラスは非常に大きくなる可能性があり、これらのステアリング ホイールとハンドブレーキ オブジェクトの操作を担当します。運転手が他の車と同じコントロールを持たない別のタイプの車に乗り込んだ場合はどうなりますか? ドライバーは、車両のコントロールを使用して車両を操作する方法を理解する必要がありますか? 余分なロジック。余分なブロブ。

これらすべての解決策は、メディエーター クラス (またはバリアント) を使用して、ドライバーが車両と対話する方法を制御することです。これは 2 つの方法のいずれかで行うことができます。ドライバーは、ドライバーが車と対話する方法を制御する車へのメディエーターを持つことができます。または、ドライバーは、対処する必要がある車の各コンポーネントまたは集合体のメディエーターを持つことができます。メディエーターはさまざまなタイプの車に再利用できるため、これはおそらくより良い解決策です。メディエーターは、コンポーネント間の双方向の関係を処理できる必要があります。

コンテナーである CCar は、メディエーターを維持し、そのコンポーネント間の関係を維持する責任があります。あるべき姿。

メディエーターは、コンポーネント間のこの関係を処理する責任があります。

class CMediatorDriverToSteeringWheel
{
CMediatorDriverToSteeringWheel( CDriver* pDriver, CSteeringWheel* pSteeringWheel )
{
m_pDriver = pDriver;
m_pSteeringWheel = pSteeringWheel;
m_pDriver->AddMediator(this);
m_pSteeringWheel->AddMediator(this);
}
};

... 

CCar::CCar( CDriver* pDriver )
{
m_pDriver = pDriver;
new CMediatorDriverToSteeringWheel( m_pDriver, &m_SteeringWheel );
new CMediatorDriverToHandbrake( m_pDriver, &m_HandBrake );
}
于 2009-06-02T13:40:13.207 に答える
0

おそらく、車とドライバーの間の双方向の関連付けが必要になるでしょう。

CCar( CDriver* pDriver ) :
     m_pDriver(pDriver)
{
    m_pDriver->SetCar(this);
}

次に、ドライバーは Car のパブリック インターフェイスを介して Car のメンバーにアクセスできます。

于 2009-05-31T16:56:04.710 に答える