Реализация шаблона наблюдателя в качестве наблюдателя MarketData

Я разрабатываю форму графического интерфейса в Qt, и мне интересно, как реализовать ObserverPattern. Форма может подписаться на множество потоков данных, отличающихся tickerId, когда приходит поток данных (доступна новая цитата), срабатывает мой PosixClient (оболочка сокета) notifyObservers() метод, что приводит к update() метод наблюдения наблюдателя.

НО:

этот update() метод void update() и мне нужно взять входящие записи данных и построить их, посчитать что-то, просто использовать их. Итак, как мне этого добиться, как передать записи данных наблюдателю? Данные доступны для Observable (объект MarketData, полученный из Observable). Когда данные поступают, я помещаю их в этот Observable и уведомляю наблюдателей.

void PosixClient::tickPrice( TickerId tickerId, TickType field, double price, int canAutoExecute) {
    printf("tradingclient_1: tickPrice: \n");
    for(std::vector<boost::shared_ptr<MarketData> >::iterator it=dataRepository.begin(); 
            it!=dataRepository.end(); it++){
        if((*it)->tickerId==tickerId){
            (*it)->tickPriceData.push_back(tickSizeRecord(field,price,canAutoExecute));
            (*it)->notifyObservers();
            //TODO: start thread to store incoming data in repository
        }
    }
}

Их void update() методы тогда вызваны. чтобы извлечь данные из этой функции, я решил передать указатель на функцию boost::function<> к нему как к обратному вызову, и Observer вызывает этот указатель на функцию, которая указывает на мой объект GUI с входящими данными из наблюдаемого в качестве аргумента. Это правильный подход?

struct MarketData : public QuantLib::Observable {
//public:
    MarketData();
    MarketData(IB::Contract c, int tickerId):c(c),tickerId(tickerId){}
    MarketData(const MarketData& orig);
    virtual ~MarketData();
    std::vector<IB::Record> tickPriceData; //market data fed in tickPrice
//private:
    IB::Contract c;
    int tickerId;
};

typedef boost::shared_ptr<MarketData> pMyObservable;
typedef boost::function<void (int tickerId, IB::Record record)> f_action_ptr;

class MarketDataObserver : public QuantLib::Observer{
public:
    MarketDataObserver(pMyObservable obs, f_action_ptr ptr)
        : observable(obs), f_ptr(ptr){
      this->registerWith(observable);
    }
    MarketDataObserver(const MarketDataObserver &observer)
      : Observer(observer),
        observable(observer.observable){ // faction_ptr is not copied!
    }

    void update(){
        data=observable->tickPriceData.back();
        //printf("new data: %l\n",data.price);
        f_ptr(observable->tickerId, data);
    }
private:
    IB::Record data;
    pMyObservable observable;
    f_action_ptr f_ptr;
};

ПОЖАЛУЙСТА, ОБРАТИТЕ ВНИМАНИЕ:

Мне известен механизм сигнала / слота Qt, но, по моему мнению, сигнал / слот Qt здесь вовсе не является решением, когда мне нужно динамически подписаться на данные, нанести их на график, показать в форме Qt, а затем удалить подписку при отмене формы. Но, возможно, я ошибаюсь. Я? Я прошу реальные, рабочие примеры из жизни, а не теоретический спор.

1 ответ

Обычная идиома Qt для паттерна наблюдателя - это действительно сигналы и слоты. Иметь источник данных, излучающий сигналы, и передавать данные в качестве аргумента сигнала. Вот как это делается в Qt - сигналы используются не только для событий GUI.

Другие вопросы по тегам