0

MediatorやObserverパターンなどの内部メッセージシステムを開発する場合、渡されたメッセージオブジェクトをカプセル化する最良の方法は何ですか?カプセル化とメッセージオブジェクト

いくつかのサービスに新しいJobを実行するように指示する次のメッセージオブジェクトを考えてみましょう。メッセージには、実行する必要があるJobが含まれています。

bool JobService::handleMessage(Message* msg) 
{ 
    switch(msg.getType()) 
    { 
    case MESSAGE_JOB: 
     runJob((dynamic_cast<NewJobMessage*>(msg))->m_Job); 
     return true; 
    case default: 
     return false; 
    } 
} 

これは、すべての罰金とダンディようだが、NewJobMessageもそれかかわらず、ジョブ・クラスについて決して知らないために持っている:今、メッセージは以下のサービスhandleMessage機能で取り扱うことができ

#define MESSAGE_JOB = 1 
class NewJobMessage: public Message 
{ 
    virtual int getType() { return MESSAGE_JOB; } 
    Job* m_Job; 
} 

それを意味のある方法で使用します。それは単にそれを運ぶだけです。

メッセージをデータに結合しないように他の方法を使用することをお勧めしますか?私はvoid*を使ってキャストしようと思っていましたが、それはハッキーだと思われ、他の人が自分のコードを解読すると混乱するかもしれません。

+0

'return'ステートメントの後にセミコロンがありません:' virtual int getType(){return MESSAGE_JOB; } ' – Azeem

答えて

0

void *の教科書のケースが適切です。実際の弱点はvoid *ですが、実行時の型チェックがありますが、getType()メソッドは大きなものです。

それを理解しないようにするには、構造を単純にしてください。

// No need to inherit from this. 
struct Message { 
    int type; 
    void * data; 
}; 

限り、あなたは、これが混乱するべきではない組織的にコードとして、型指定されていないデータがstandard approach for message queuesです。

+0

' getType() 'がちょっと余計だったと思った今、この構造体から継承しなければならない2つのポインタを送信する必要があるというメッセージがあるとします。あるいは、間接的に二重になり、2つのポインタを含む構造体に 'void * data'ポイントを持ちます。 –

+0

はい、' void * data'は2つのポインタを含む構造体を指します。そのような場合には、 'struct Message'に別のポインタ構造体を追加することができます。実際には、ウィンドウのMSG構造にタイムスタンプ、カーソルのx/y、メッセージを送信するウィンドウの識別子と2つの汎用ポインタ/ intが含まれています。いくつかのメッセージは余分のフィールドを必要とせず、余分なフィールドをサポートするためには間接レベルが必要なものもあるため、常にトレードオフがあります。 – QuestionC

+0

'getType()'は不必要ではありません。メッセージ待ち行列メッセージは、基本的にそのデータと、そのデータをどのように処理するかの指標を含む必要があります。タイプ情報は、データの取り扱い方法を表します。 'void *'はデータを表現します。 メッセージは、実行する必要のあるジョブを含んではいけません。メッセージ*は、実行する必要のあるジョブを表します。メッセージ待ち行列にメッセージを渡すことは、第2のスレッドで関数を呼び出す1つのスレッドに類似している。型は関数名です。データは関数の引数です。 – QuestionC

0

これらのメッセージがどのように渡されているか、どのくらい行くことができるかは言及していませんでしたが、一般的にネイティブオブジェクトを渡すことについてSTRONGLYにアドバイスします。それは苦痛と道に苦しむためのレシピです。これはメンテナンスとデバッグの悪夢、セキュリティアタックベクトル、設計結合問題です。このシステムが後で拡張されるときには悪化します(常にそうであるため)。

だから、これに対処するいくつかの方法があります。

  • は、CDRを使用して情報やジョブ情報をエンコードするためにいくつかのような方法をエンコードします。レシーバは、同じ言語、システム、またはバイトサイズ/オーダーでない場合でも、CDRを元に戻して情報を戻します。コーディングするのはちょっと面倒ですが、計算上またはスペース上の費用がかかりません。
  • あなたの好みや経験、データの情報の種類に応じて、JSONやXMLのようなより高いレベルへのリクエストをマーシャルしてください。これは通常、第三者の図書館の援助ではかなり簡単ですが、テキストとの変換やテキストの変換は少し高価です。また、問題を診断し、通過中のものを調べる方がずっと簡単です。

これらの要求を処理して転送する必要がある速度が非常に高く、処理が追いつかない場合を除いて、私はJSONに傾いています。現代のC++ライブラリの助けを借りてJSONを処理するのはかなり簡単です。

+0

これはすべて同じプロセスで内部的に処理されます。私は、自分のシステムのさまざまなコンポーネントと、これらのメッセージコマンドを通じて通信する要素を切り離したいだけです。シリアライゼーションは私がここで欲しいものではありませんが、私が必要とする他の場所について考えることができます。ありがとう! –