我在Qt中开发GUI表单,我想知道如何实现ObserverPattern。表单可以订阅由tickerId区分的许多数据流,当数据流到达时(新引用可用)我的PosixClient(套接字包装器)触发notifyObservers()
方法导致update()
方法正在执行的观察者。
这个update()
方法是void update()
,我需要接收传入的数据记录并绘制它们,计算一些东西,只需使用它们。那么如何实现这一目标,如何将数据记录传递给观察者呢?
数据可用于Observable(从Observable派生的MarketData对象)。当数据到达时,我将其推入此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对象,并将来自observable的传入数据作为参数。 这是正确的做法吗?
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表单上显示,然后在Form是时删除订阅取消。但也许我错了。我呢?我要求生活中的实际例子,而不是理论上的争议。
答案 0 :(得分:1)
观察者模式通常的Qt习语确实是信号和时隙。让数据源发出信号并将数据作为信号的参数传递。这是在Qt中完成的 - 信号不仅仅用于GUI事件。