Путаница с дизайном функции обратного вызова - PullRequest
1 голос
/ 30 ноября 2010

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

У меня есть класс MessageConsumer, который должен обрабатывать сообщения разных типов. Я объединил все функции-обработчики в абстрактный базовый класс под названием MessageHandlerBase. Пользователи библиотеки будут наследовать это и писать свои MessageHandler классы.

Соответствующие части определения MessageConsumer:

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

И определение MessageHandlerBase равно

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

Пользователи обычно просто заботятся об обработке сообщений типа 1 и 2, поэтому я просто сделал их чисто виртуальными.

Моя большая проблема заключается в следующем: При реализации своих собственных MessageHandler классов handle_message_type_1 и handle_message_type_2 методов пользователям необходим доступ к методам одного (или, возможно, нескольких) из их вспомогательных классов. Как сделать эти классы доступными для MessageHandler, не делая их глобальными? Я могу передать класс в качестве void* аргумента handle_message_type_1, но я не хочу этого, потому что (i) что, если мне нужно передать более одной функции, и (ii) тогда мне нужно изменить вызов в MessageConsumer; Я хочу полностью абстрагировать эти детали обработки сообщений от MessageConsumer.

Есть ли более элегантный способ обработки всего этого?

1 Ответ

2 голосов
/ 30 ноября 2010

Как эти классы можно сделать доступными для MessageHandler, не делая их глобальными?

Пользователи должны получать из вашего класса.Что мешает им поместить все виды членов данных в свои производные, ссылаясь на то, что им нужно?

Это главное преимущество использования функторов вместо указателей функций: void* userData устаревает.

...