1

入力ストリームからヘッダーを読み取り、メッセージヘッダーで定義されたタイプに基づいて適切なメッセージタイプを作成する基本的なメッセージファクトリを実装するためのアイデアを探しています。

だから私は次のようなものを持っています(大まかに..そして、より良いパラダイムがここに提示されている場合、私は喜んでデザインを変更します)

class MessageHeader { 
   public String type;
}

class MessageA extends Message {
   public static final String MESSAGE_TYPE = "MSGA";
   public MessageA (DataInputStream din) {
      var1 = din.readInt ();
      var2 = din.readInt ()
      // etc
   }
} 

そして私は本質的にこのようなことをしたい:

MessageHeader header = ... read in from stream.

if (header.type == MessageA.MESSAGE_TYPE) {
   return new MessageA (din);
} else if (header.type == MessageB.MESSAGE_TYPE) {
   return new MessageB (din);
}

このスキームは機能しますが、どうにかして Map と Interface を使用するより良い方法があると思います...

public interface MessageCreator {
  public Message create (DataInputStream);
}

Map <String, MessageCreater> factory = new Map <String, MessageCreator> ();
factory.put (MessageTypeA.MESSAGE_TYPE, new MessageCreator () { 
                          public Message create (DataInputStream din) {
                              return new MessageA (din); }});
...
// Read message header
Message createdMessage = Map.get (header.type).create (din);

しかし、メッセージを使用したいときはいつでも、instanceof を使用して正しいサブクラスにキャストする必要があります。

3番目の(より良い?)オプションはありますか?テンプレートを使用してこれを実現する方法があるかもしれません。どんな助けでも大歓迎です。ありがとう

編集:メッセージを関数に「ディスパッチ」したいことに注意することが重要だと思います。だから本質的に私は本当にこれをしたい:

MessageHeader header = ... read in from stream.

if (header.type == MessageA.MESSAGE_TYPE) {
   handleMessageA (new MessageA (din));
} else if (header.type == MessageB.MESSAGE_TYPE) {
   handleMessageB (new MessageB (din))
}

なので、工場と発送を組み合わせたパターンが最適です。

4

1 に答える 1

1

メッセージを作成する人が実際にハンドラーにディスパッチするのはどうですか。

したがって、次のようなハンドラ インターフェイスを追加します。

public interface MessageHandler {
    void handleTypeA(MessageA message);
    void handleTypeB(MessageB message);
}

次に、メッセージオブジェクトを返す代わりにハンドラーで正しいメソッドを呼び出すことを除いて、基本的に MessageCreator と同じディスパッチャーを作成します。

public interface MessageDispatcher {
    void createAndDispatch(DataInputStream input, MessageHandler handler);
}

実装は、投稿した最初のコード スニペットとほぼ同じです。

public void createAndDispatch(DataInputStream input, MessageHandler handler) {
    MessageHeader header = ... read in from stream.

    if (header.type == MessageA.MESSAGE_TYPE) {
       handler.handleTypeA(new MessageA (din));
    } else if (header.type == MessageB.MESSAGE_TYPE) {
       handler.handleTypeB(new MessageB (din));
    }
}

これで、コード内で switch または if/else if を実行する必要がある場所が 1 つだけになりました。

于 2010-10-12T04:23:06.970 に答える