2010-10-12 4 views
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); 
} 

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

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

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

+0

Это действительно не имеет ничего общего с сокетами. Вы просто разбираете входной поток здесь. – EJP

ответ

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

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

+0

Да, я думаю, я пойду с упрощенным подходом к переключению. У меня будет только 15-20 различных типов сообщений. Я думаю, что я хотел сделать что-то необычное только ради того, чтобы делать что-то классное ... иногда проще – Shaun