2010-10-12 9 views
1

Je cherche des idées pour implémenter une fabrique de messages de base qui lit un en-tête à partir d'un flux d'entrée et crée le type de message approprié en fonction du type défini dans l'en-tête du message.Socket-based Message Factory

J'ai donc quelque chose comme (à peu près .. et je suis prêt à changer la conception si un meilleur paradigme est présenté ici)

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

et je veux essentiellement faire quelque chose comme ceci:

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

Bien que ce système fonctionne, je me sens comme il pourrait y avoir une meilleure méthode utilisant une carte et une interface en quelque sorte ...

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

Mais quand je veux utiliser le message, je dois utiliser instanceof et cast dans la sous-classe correcte.

Existe-t-il une 3ème option (meilleure?)? Peut-être y at-il un moyen d'y parvenir en utilisant des modèles. Toute aide est appréciée. Merci

Editer: Je suppose qu'il est important de noter que je veux "envoyer" le message à une fonction. Donc, essentiellement, je veux vraiment faire ceci:

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

Ainsi, un modèle qui intègre l'usine et une expédition serait parfait

+0

Cela n'a vraiment rien à voir avec Sockets. Vous êtes en train d'analyser un flux d'entrée ici. – EJP

Répondre

1

Que diriez-vous de laisser le gars qui crée les messages d'expédition effectivement à un gestionnaire.

Vous ajouteriez une interface de gestionnaire comme ceci:

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

Ensuite, vous auriez un répartiteur qui est essentiellement la même chose que votre MessageCreator, sauf qu'il appelle la méthode correcte sur le gestionnaire au lieu de renvoyer l'objet de message.

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

La mise en œuvre est alors presque identique au premier extrait de code que vous avez posté:

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

Maintenant vous avez seulement un endroit dans le code où vous devez faire un interrupteur ou if/else si et après que tout est tapé spécifiquement et il n'y a plus de casting.

+0

Oui, je pense que je vais aller avec l'approche de changement simpliste. Je n'aurai que 15-20 types de messages différents. Je pense que je voulais faire quelque chose de fantaisiste juste pour faire quelque chose de cool ... parfois plus simple c'est mieux – Shaun