0

私のシナリオでは、Messageクラスを介して通信するコンポーネントAとコンポーネントBがあります。

私のメッセージクラスは次のようになります

class Message {
    virtual void prepare();
    virtual void parse();
    virtual void handle();
};

メッセージは、Messageクラスのサブクラスです。次に例を示します。

class MessageA: public Message {
    void prepare() {
    ...
    }
    void parse() {
    ...
    }
    void handle() {
    componentA->executeFunctionABC(); // componentA is a global pointer
    }
};

コンポーネントAはMessageAでコンパイルされます

コンポーネントBはMessageAでコンパイルされます

つまり、コンポーネントAがコンポーネントBにメッセージを送信する場合、MessageAオブジェクトをインスタンス化し、prepare()して送信します。コンポーネントBは、ソケットを介してメッセージを受信すると、メッセージをparse()してhandle()します。

私の問題は、handle()関数にあります。メッセージの受信者のみがhandle()関数を呼び出します。handle()関数の実装では、受信コンポーネントの関数を含む特定のルーチンを実行する必要があります。

これで、次のようにPREPROCESSORを使用してこれを解決できます。

void handle() {
#ifdef COMPILE_FOR_COMPONENT_A
componentA->executeFunctionABC();
#endif
}

しかし、それは醜いように見えます。これを正しく行うことができるデザインパターンはありますか?

4

3 に答える 3

0

メッセージ自体を、処理、解析、準備などのメッセージに対するアクションから分離できますか?

MessageHandler、MessageParser、MessagePreparer の観点から考えてみてください。メッセージのデータにアクセスするために、共通の Message インターフェイスのどの部分を使用できますか? 何が違うの?

これがうまくいけば、コンポーネント A には MessageA_Preparer と MessageB_Handler と _Parser が必要になります。コンポーネント B には、MessageB_Preparer、MessageB_Handler、および _Parser が必要です。

于 2012-07-23T03:10:52.250 に答える
0

これは、handle() 関数の処理に関する既存の問題に対する回答ではありませんが、メッセージに prepare()、parse() および handle( )? prepare() を処理する送信側クラスと parse() を処理する受信側クラスが必要だと思います。また、handle() の実装方法によっては、それもあるかもしれません。

Message クラスにメッセージだけを含め、送信側クラスと受信側クラスが他の機能を処理するほうがよいのではないでしょうか?

于 2012-07-23T04:18:30.360 に答える
0

コンポーネントが共通のインターフェースを実装している場合、コンポーネントをhandleメソッドに渡すことができます。

class Component {
  virtual void executeFunctionABC() = 0;
  virtual void executeFunctionDEF() = 0;
}

class MessageA : public Message {
  void handle(Component *c) {
    c->executeFunctionABC();
  }
}

コンポーネントがメッセージを受信すると、次のように呼び出します。

message->handle(this);

また、あなたの説明から、主にメッセージの作成/復元に使用されるように思われるため、クラスの仮想メソッドではなく、ファクトリ メソッド (静的メソッドprepareまたは別のクラスのいずれか) にします。parseMessageMessageFactoryMessage


編集:または、コンポーネントごとに個別のメソッドを使用して、訪問者パターンを使用することもできます。handle

class MessageA : public Message {
  void handle(ComponentA *c) {
    c->executeFunctionABC();
  }

  void handle(ComponentB *c) {
    ...
  }
}

これは、非常に異なる機能を持ついくつかのコンポーネントがある場合にうまく機能します。同様の機能を持つコンポーネントがある場合、インターフェイス アプローチはうまく機能します。


編集 2:コンポーネントを完全に切り離すには、前の 2 つのソリューションのハイブリッドを使用できます。

class MessageHandler {
  virtual void handle(MessageA *msg) = 0;
  virtual void handle(MessageB *msg) = 0;
}

class MessageA : public Message {
  void handle(MessageHandler *handler) {
    handler->handle(this);
  }
}

class ComponentA : public MessageHandler {
  void handle(MessageA *msg) {
    executeFunctionABC();
  }
}

最終的にはコンポーネントのインターフェースになりますが、メッセージと同数のメソッドしかありません。これは事実上、プリプロセッサ ディレクティブによって実現されます。

于 2012-07-23T02:44:51.167 に答える