2010-11-30 10 views
1

メッセージキューからの受信メッセージを傍受して処理するためのライブラリを設計しています。ライブラリユーザーは、受信したさまざまな種類のメッセージに対して独自のメッセージ処理機能を作成します。コールバック関数の設計についての混乱

私は異なる種類のメッセージを処理する必要があるMessageConsumerクラスを持っています。すべてのハンドラ関数を、MessageHandlerBaseという抽象基本クラスにまとめました。ライブラリユーザーはこれを継承し、独自のMessageHandlerクラスを作成します。 MessageConsumer定義の

関連部品:

class MessageConsumer { 
protected: 
    const MessageHandlerBase* m_mesgHandler;   
public: 
    MessageConsumer(const std::string& brokerURI, 
        const std::string& inputQueueName, 
        const MessageHandlerBase* messageHandler); 
    virtual ~MessageConsumer() { this->cleanup(); } 
    void runConsumer(); 

    virtual void onMessage(const Message& message) 
    { 
     // code to receive and parse messages ... 

     if (message is of type 1) { 
      m_mesgHandler->handle_message_type_1(message); 
     else if (message is of type 2) { 
      m_mesgHandler->handle_message_type_2(message); 
     // ... and so on for different types of messages 
    } 
}; 

そしてMessageHandlerBase定義は

class MessageHandlerBase { 
    public: 
     virtual void handle_message_type_1(const Message&) const =0; 
     virtual void handle_message_type_2(const Message&) const =0; 
     virtual void handle_cms_exception() const {} 
     virtual void handle_transfer_interrupted() const {} 
     virtual void handle_transfer_resumed() const {} 
}; 

ユーザーは通常、ちょうどので、私はちょうどそれらの純粋仮想作られたタイプ1 & 2のメッセージを処理する気になりますされます。自分のMessageHandlerクラスのhandle_message_type_1handle_message_type_2メソッドを実装しながら、ユーザーが自分のヘルパークラスの1つ(またはおそらくそれ以上)からのメソッドにアクセスする必要があります。

私の大きな問題は、これがあります。これらのクラスは、グローバルにすることなく、どのようにしてMessageHandlerに利用できますか?私はvoid*引数としてhandle_message_type_1に渡すことができますが、(i)複数の関数を渡す必要があり、(ii)呼び出しを変更する必要がある場合は、MessageConsumerで呼び出しを変更する必要はありません。私はMessageConsumerからこれらのメッセージ処理の詳細を完全に抽象化したいと思います。

この全体をよりうまく扱う方法はありますか?

答えて

2

MessageHandlerではどのようにこれらのクラスをグローバルにすることなく利用できますか?

ユーザーはあなたのクラスから派生する必要があります。あらゆる種類のデータメンバーを彼らの派生物に入れ、必要なものを参照するのを止めるのは何ですか?

これは、関数ポインタの代わりにファンクタを使用した場合の主な利点です。は廃止されました。

+0

ありがとうございます。彼らは独自のハンドラを実装するために 'MessageHandlerBase'から派生します。しかし、ヘルパークラスは既に実装されているので、そのコードを変更することは望ましくありません。例えば、type_1のメッセージを扱うときに呼び出される必要がある 'track()'メソッドを持つ 'Tracker'というクラスがあります。この場合、 'MessageHandlerBase'と' Tracker'から複数の継承を使うべきでしょうか? – recipriversexclusion

+0

派生した 'MessageHandler'オブジェクトを作成するとき、ユーザーは使用する必要があるヘルパークラスへのポインタを渡し、子クラスのプライベートデータ内にそれらを格納します。 –

+1

@recipriversexclusion MessageHandlerBaseを実装しているクラスは、次のことができます:a)他の必要なクラスから派生します。 b)他の必要なオブジェクトを含む。 c)ポインタまたは参照を介して他のオブジェクトを参照する。 3つのオプションはすべて一般的に実行可能です。あなたのプログラムの設計に最も合ったもの(またはその組み合わせ)を使用してください。 – TheUndeadFish