2010-11-30 31 views
1

Je conçois une bibliothèque qui sera utilisée pour intercepter et traiter les messages entrants provenant d'une file d'attente de messages. Les utilisateurs de la bibliothèque écriront leurs propres fonctions de gestion des messages pour différents types de messages reçus.Confusion à propos de la conception de la fonction de rappel

J'ai une classe MessageConsumer qui doit gérer des messages de différents types. J'ai combiné toutes les fonctions du gestionnaire dans une classe de base abstraite appelée MessageHandlerBase. Les utilisateurs de la bibliothèque en hériteront et écriront leurs propres classes MessageHandler.

parties pertinentes de la MessageConsumer définition:

class MessageConsumer { 
protected: 
    const MessageHandlerBase* m_mesgHandler;   
public: 
    MessageConsumer(const std::string& brokerURI, 
        const std::string& inputQueueName, 
        const MessageHandlerBase* messageHandler); 
    virtual ~MessageConsumer() { this->cleanup(); } 
    void runConsumer(); 

    virtual void onMessage(const Message& message) 
    { 
     // code to receive and parse messages ... 

     if (message is of type 1) { 
      m_mesgHandler->handle_message_type_1(message); 
     else if (message is of type 2) { 
      m_mesgHandler->handle_message_type_2(message); 
     // ... and so on for different types of messages 
    } 
}; 

Et la définition MessageHandlerBase est

class MessageHandlerBase { 
    public: 
     virtual void handle_message_type_1(const Message&) const =0; 
     virtual void handle_message_type_2(const Message&) const =0; 
     virtual void handle_cms_exception() const {} 
     virtual void handle_transfer_interrupted() const {} 
     virtual void handle_transfer_resumed() const {} 
}; 

Les utilisateurs habituellement vont simplement se soucier de la gestion des messages de type 1 & 2 donc je viens de faire les pur virtuel .

Mon gros problème est le suivant: Alors que la mise en œuvre de leur propre MessageHandler méthodes de classe handle_message_type_1 et handle_message_type_2, les utilisateurs ont besoin d'accéder à des méthodes d'un (ou peut-être plus) de leurs classes d'aide. Comment ces classes peuvent-elles être mises à la disposition de MessageHandler, sans les rendre globales? Je peux passer la classe en tant qu'argument void* à handle_message_type_1 mais je ne veux pas parce que (i) que faire si je dois passer plus d'une fonction et (ii) alors je dois changer l'appel en MessageConsumer; Je veux totalement abstraire ces détails de traitement des messages de MessageConsumer.

Y a-t-il une façon plus élégante de gérer tout cela?

Répondre

2

Comment ces classes peuvent-elles être mises à la disposition de MessageHandler, sans les rendre globales?

Les utilisateurs doivent dériver de votre classe. Qu'est-ce qui les empêche de mettre toutes sortes de membres de données dans leurs dérivés, référençant ce dont ils ont besoin?

C'est l'avantage principal de l'utilisation de foncteurs au lieu de pointeurs de fonction: Cela rend void* userData obsolète.

+0

Merci, oui, ils proviendront de 'MessageHandlerBase' pour implémenter leurs propres gestionnaires. Cependant, les classes auxiliaires sont déjà implémentées, il n'est donc pas souhaitable de changer ce code. Par exemple, il existe une classe appelée 'Tracker' avec une méthode' track() 'qui doit être appelée lors de la gestion des messages de type_1. Devraient-ils utiliser l'héritage multiple, de 'MessageHandlerBase' et' Tracker' dans ce cas? – recipriversexclusion

+0

Lorsqu'ils créent l'objet 'MessageHandler' dérivé, les utilisateurs transmettent les pointeurs vers les classes auxiliaires qu'ils doivent utiliser et les stockent dans les données privées de la classe enfant. –

+1

@recipriversexclusion Toute classe implémentant MessageHandlerBase pourrait: a) dériver de toutes les autres classes nécessaires; b) contenir tout autre objet nécessaire; c) référence d'autres objets via des pointeurs ou des références. Les trois options sont viables en général. Utilisez n'importe lequel (ou une combinaison) qui a le plus de sens pour la conception de votre programme. – TheUndeadFish