Фабрика сообщений на основе сокетов - PullRequest
1 голос
/ 12 октября 2010

Я ищу некоторые идеи по реализации базовой фабрики сообщений, которая считывает заголовок из входного потока и создает соответствующий тип сообщения на основе типа, определенного в заголовке сообщения.

Так что у меня есть что-то вроде (примерно .. и я готов изменить дизайн, если здесь представлена ​​лучшая парадигма)

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);
}

Хотя эта схема работает, я чувствую, что мог бы быть лучший способ, используя Карту и Интерфейс как-то ...

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 и приводить к правильному подклассу.

Есть ли третий (лучший?) Вариант? Может быть, есть способ сделать это с помощью шаблонов. Любая помощь приветствуется. Спасибо

Редактировать: Я думаю, важно отметить, что я хочу "отправить" сообщение в функцию. По сути, я действительно хочу сделать это:

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))
}

Таким образом, шаблон, который включает в себя фабрику и отправку, будет идеальным

1 Ответ

1 голос
/ 12 октября 2010

Как насчет того, чтобы позволить парню, который создает сообщения, отправлять его обработчику?

Таким образом, вы бы добавили интерфейс обработчика, подобный этому:

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));
    }
}

Теперь у вас есть только одно место в коде, где вы должны сделать переключение или если / иначе, если и после этого все специально набрано и больше нет преобразования.

...